Kapan menggunakan kelas abstrak vs. antarmuka di C #

Saat mendesain aplikasi, penting untuk mengetahui kapan harus menggunakan kelas abstrak dan kapan menggunakan antarmuka. Meskipun kelas dan antarmuka abstrak tampak serupa dalam beberapa hal, ada perbedaan utama yang akan menentukan pilihan terbaik untuk apa yang ingin Anda capai. Dalam posting blog ini saya akan membahas perbedaan tersebut dan bagaimana memutuskan kapan harus menggunakan yang mana.

Jawaban singkatnya: Kelas abstrak memungkinkan Anda membuat fungsionalitas yang dapat diterapkan atau ditimpa oleh subkelas. Antarmuka hanya memungkinkan Anda untuk menentukan fungsionalitas, bukan mengimplementasikannya. Dan sementara sebuah kelas hanya dapat memperluas satu kelas abstrak, ia dapat memanfaatkan banyak antarmuka. 

C # kelas abstrak menjelaskan

Kelas abstrak adalah jenis kelas khusus yang tidak dapat dibuat instance-nya. Kelas abstrak dirancang untuk diwarisi oleh subkelas yang mengimplementasikan atau mengganti metodenya. Dengan kata lain, kelas abstrak diimplementasikan sebagian atau tidak diimplementasikan sama sekali. Anda dapat memiliki fungsionalitas dalam kelas abstrak Anda — metode dalam kelas abstrak dapat berupa abstrak dan konkret. Kelas abstrak dapat memiliki konstruktor — ini adalah satu perbedaan utama antara kelas abstrak dan antarmuka. Anda dapat memanfaatkan kelas abstrak untuk mendesain komponen dan menentukan beberapa tingkat fungsionalitas umum yang harus diimplementasikan oleh kelas turunan.

C # antarmuka menjelaskan

Antarmuka pada dasarnya adalah kontrak — ia tidak memiliki implementasi apa pun. Antarmuka hanya dapat berisi deklarasi metode; itu tidak bisa berisi definisi metode. Anda juga tidak dapat memiliki data anggota dalam sebuah antarmuka. Sementara kelas abstrak dapat berisi definisi metode, bidang, dan konstruktor, antarmuka hanya dapat memiliki deklarasi kejadian, metode, dan properti. Metode yang dideklarasikan dalam sebuah antarmuka harus diimplementasikan oleh kelas-kelas yang mengimplementasikan antarmuka tersebut. Perhatikan bahwa sebuah kelas dapat mengimplementasikan lebih dari satu antarmuka tetapi hanya memperluas satu kelas. Kelas yang mengimplementasikan antarmuka harus mengimplementasikan semua anggotanya. Seperti kelas abstrak, antarmuka tidak dapat dibuat instance-nya.

Haruskah saya menggunakan kelas abstrak atau antarmuka?

Kelas abstrak memberi Anda fleksibilitas untuk memiliki metode konkret tertentu dan beberapa metode lain yang harus diterapkan oleh kelas turunan. Sebaliknya, jika Anda menggunakan antarmuka, Anda perlu mengimplementasikan semua metode di kelas yang memperluas antarmuka. Kelas abstrak adalah pilihan yang baik jika Anda memiliki rencana untuk perluasan di masa mendatang - misalnya, jika perluasan di masa mendatang kemungkinan besar dalam hierarki kelas. Jika Anda ingin memberikan dukungan untuk perluasan di masa mendatang saat menggunakan antarmuka, Anda harus memperluas antarmuka dan membuat yang baru.

Pada catatan yang berbeda, mudah untuk menambahkan antarmuka baru ke hierarki jika perlu. Namun, jika Anda sudah memiliki kelas abstrak dalam hierarki, Anda tidak dapat menambahkan yang lain — misalnya, Anda dapat menambahkan kelas abstrak hanya jika tidak ada yang tersedia. Anda harus menggunakan antarmuka jika Anda menginginkan kontrak pada beberapa perilaku atau fungsionalitas. Anda tidak boleh menggunakan antarmuka jika Anda perlu menulis kode yang sama untuk metode antarmuka. Dalam kasus ini, Anda harus menggunakan kelas abstrak, mendefinisikan metode satu kali, dan menggunakannya kembali sesuai kebutuhan. Gunakan antarmuka untuk memisahkan kode aplikasi Anda dari implementasi spesifiknya, atau untuk membatasi akses ke anggota jenis tertentu.

Sebagaimana dokumentasi antarmuka Microsoft menyatakan:

Dengan menggunakan antarmuka, Anda dapat, misalnya, menyertakan perilaku dari berbagai sumber dalam sebuah kelas. Kemampuan itu penting dalam C # karena bahasa tersebut tidak mendukung banyak pewarisan kelas. Selain itu, Anda harus menggunakan antarmuka jika ingin menyimulasikan warisan untuk struct, karena mereka tidak dapat benar-benar mewarisi dari struct atau kelas lain.

Implementasi antarmuka implisit dan eksplisit

Antarmuka dapat diimplementasikan secara implisit maupun eksplisit. Izinkan saya menjelaskan bagaimana kedua penerapan ini berbeda. Pertimbangkan sebuah antarmuka bernama IBusinessLogic.

antarmuka publik IBusinessLogic

{

   void Initialize ();

}

Kelas berikut bernama BusinessLogicmengimplementasikan IBusinessLogicantarmuka.

kelas umum BusinessLogic: IBusinessLogic

{

   public void Initialize ()

   {

       // Beberapa kode

   }

}

Anda dapat membuat instance BusinessLogickelas secara eksplisit dan kemudian memanggil Initialize()metode seperti yang ditunjukkan di bawah ini.

 IBusinessLogic businessLogic = new BusinessLogic ();

businessLogic.Initialize ();

Cuplikan kode berikut mengilustrasikan bagaimana Anda dapat mengimplementasikan IBusinessLogicantarmuka secara implisit.

kelas umum BusinessLogic: IBusinessLogic

{

   void IBusinessLogic.Initialize ()

   {

   }

}

Sekarang Anda dapat menjalankan Initialize()metode dengan cara yang sama menggunakan referensi ke IBusinessLogicantarmuka. Perbedaan dalam kedua pendekatan tersebut adalah ketika Anda mengimplementasikan antarmuka secara eksplisit di kelas Anda, Anda dibatasi untuk menjalankan metode antarmuka Anda dengan menggunakan referensi ke antarmuka saja. Oleh karena itu potongan kode berikut tidak akan berfungsi, yaitu tidak dapat dikompilasi.

 BusinessLogic businessLogic = new BusinessLogic ();

businessLogic.Initialize ();

Bagaimana melakukan lebih banyak di C #:

  • Kapan menggunakan kelas abstrak vs. antarmuka di C #
  • Bagaimana bekerja dengan AutoMapper di C #
  • Cara menggunakan ekspresi lambda di C #
  • Cara bekerja dengan delegasi Action, Func, dan Predicate di C #
  • Bagaimana bekerja dengan delegasi di C #
  • Bagaimana menerapkan logger sederhana di C #
  • Bagaimana bekerja dengan atribut di C #
  • Bagaimana bekerja dengan log4net di C #
  • Bagaimana menerapkan pola desain repositori di C #
  • Bagaimana bekerja dengan refleksi di C #
  • Bagaimana bekerja dengan filesystemwatcher di C #
  • Bagaimana melakukan inisialisasi malas di C #
  • Bagaimana bekerja dengan MSMQ di C #
  • Bagaimana bekerja dengan metode ekstensi di C #
  • Bagaimana kami ekspresi lambda di C #
  • Kapan menggunakan kata kunci volatile di C #
  • Cara menggunakan kata kunci hasil di C #
  • Bagaimana menerapkan polimorfisme di C #
  • Cara membuat penjadwal tugas Anda sendiri di C #
  • Bagaimana bekerja dengan RabbitMQ di C #
  • Bagaimana bekerja dengan tupel di C #
  • Menjelajahi metode virtual dan abstrak di C #