Kelas abstrak vs Antarmuka di Java

88

Saya diberi pertanyaan, saya ingin jawaban saya ditinjau di sini.

T: Dalam skenario mana lebih tepat untuk memperluas kelas abstrak daripada mengimplementasikan antarmuka?

A: Jika kami menggunakan pola desain metode template.

Apakah saya benar ?

Saya minta maaf jika saya tidak dapat menyatakan pertanyaan dengan jelas.
Saya tahu perbedaan mendasar antara kelas abstrak dan antarmuka.

1) gunakan kelas abstrak ketika persyaratannya sedemikian rupa sehingga kita perlu mengimplementasikan fungsionalitas yang sama di setiap subkelas untuk operasi tertentu (mengimplementasikan metode) dan fungsionalitas yang berbeda untuk beberapa operasi lain (hanya tanda tangan metode)

2) gunakan antarmuka jika Anda perlu meletakkan tanda tangan yang sama (dan implementasi yang berbeda) sehingga Anda dapat mematuhi implementasi antarmuka

3) kita dapat memperluas maksimal satu kelas abstrak, tetapi dapat mengimplementasikan lebih dari satu antarmuka

Mengulangi pertanyaan: Apakah ada skenario lain, selain yang disebutkan di atas, di mana secara khusus kita perlu menggunakan kelas abstrak (salah satunya adalah lihat apakah pola desain metode template secara konseptual hanya didasarkan pada ini)?

Antarmuka vs. kelas Abstrak

Memilih di antara keduanya sangat bergantung pada apa yang ingin Anda lakukan, tetapi untungnya bagi kami, Erich Gamma dapat sedikit membantu kami.

Seperti biasa, ada trade-off, antarmuka memberi Anda kebebasan berkenaan dengan kelas dasar, kelas abstrak memberi Anda kebebasan untuk menambahkan metode baru nanti . - Erich Gamma

Anda tidak dapat pergi dan mengubah Antarmuka tanpa harus mengubah banyak hal lain dalam kode Anda, jadi satu-satunya cara untuk menghindarinya adalah dengan membuat Antarmuka baru, yang mungkin tidak selalu merupakan hal yang baik.

Abstract classessebaiknya digunakan untuk objek yang terkait erat. Interfaceslebih baik dalam menyediakan fungsionalitas umum untuk kelas yang tidak terkait.

Pelajar
sumber
kemungkinan duplikat dari Antarmuka vs Kelas Abstrak (OO umum)
bezmax
Ini bukan duplikat. OP ingin tahu kapan harus memperluas kelas abstrak daripada mengimplementasikan antarmuka. Dia tidak ingin tahu kapan harus menulis kelas atau antarmuka abstrak. Kelas dan antarmuka abstraknya sudah ditulis. Hd ingin tahu apakah akan memperpanjang atau menerapkan.
Shiplu Mokaddim
1
@ shiplu.mokadd.im Itu adalah perbedaan tanpa perbedaan. Anda tidak dapat menggunakan kelas abstrak tanpa memperluasnya. Omong kosong Anda di sini tampaknya sama sekali tidak berguna.
pengguna207421

Jawaban:

87

Kapan Menggunakan Antarmuka

Antarmuka memungkinkan seseorang untuk memulai dari awal untuk mengimplementasikan antarmuka Anda atau mengimplementasikan antarmuka Anda dalam beberapa kode lain yang tujuan asli atau utamanya sangat berbeda dari antarmuka Anda. Bagi mereka, antarmuka Anda hanyalah insidental, sesuatu yang harus ditambahkan ke kode mereka untuk dapat menggunakan paket Anda. Kerugiannya adalah setiap metode di antarmuka harus bersifat publik. Anda mungkin tidak ingin membeberkan semuanya.

Kapan Menggunakan kelas Abstrak

Kelas abstrak, sebaliknya, menyediakan lebih banyak struktur. Biasanya mendefinisikan beberapa implementasi default dan menyediakan beberapa alat yang berguna untuk implementasi penuh. Tangkapannya adalah, kode yang menggunakannya harus menggunakan kelas Anda sebagai basis. Itu mungkin sangat merepotkan jika programmer lain yang ingin menggunakan paket Anda telah mengembangkan hierarki kelas mereka sendiri secara mandiri. Di Java, sebuah kelas hanya dapat mewarisi dari satu kelas dasar.

Kapan Menggunakan Keduanya

Anda dapat menawarkan yang terbaik dari kedua dunia, antarmuka, dan kelas abstrak. Pelaksana dapat mengabaikan kelas abstrak Anda jika mereka memilih. Satu-satunya kelemahan melakukan itu adalah memanggil metode melalui nama antarmuka mereka sedikit lebih lambat daripada memanggilnya melalui nama kelas abstrak mereka.

DivineDesert
sumber
Saya pikir OP ingin tahu kapan harus memperluas kelas abstrak daripada mengimplementasikan antarmuka
Shiplu Mokaddim
@ shiplu.mokadd.im Sebenarnya OP menanyakan pertanyaan yang sangat spesifik, yang jawabannya 'ya' atau 'tidak'.
pengguna207421
4
Kamu benar. Namun di SO kami menjawab ya / tidak dengan penjelasan yang tepat.
Shiplu Mokaddim
1
@ shiplu.mokadd.im Saya tidak mengerti bagaimana hal itu memberi Anda izin untuk salah menyatakan pertanyaannya.
pengguna207421
Hanya atas dasar pernyataan tunggal ini If we are using template method design patternKami tidak bisa mengatakan YESatauNO
DivineDesert
31

mengulangi pertanyaan: ada skenario lain selain yang disebutkan di atas di mana secara khusus kita perlu menggunakan kelas abstrak (salah satunya lihat adalah pola desain metode template secara konseptual hanya didasarkan pada ini)

Ya, jika Anda menggunakan JAXB. Itu tidak suka antarmuka. Anda sebaiknya menggunakan kelas abstrak atau mengatasi batasan ini dengan obat generik.

Dari postingan blog pribadi :

Antarmuka:

  1. Sebuah kelas dapat mengimplementasikan banyak antarmuka
  2. Antarmuka tidak dapat memberikan kode apa pun
  3. Antarmuka hanya dapat mendefinisikan konstanta final statis publik
  4. Antarmuka tidak dapat menentukan variabel contoh
  5. Menambahkan metode baru memiliki efek riak pada kelas implementasi (pemeliharaan desain)
  6. JAXB tidak dapat menangani antarmuka
  7. Antarmuka tidak dapat memperluas atau mengimplementasikan kelas abstrak
  8. Semua metode antarmuka bersifat publik

Secara umum, antarmuka harus digunakan untuk mendefinisikan kontrak (apa yang ingin dicapai, bukan bagaimana mencapainya).

Kelas Abstrak:

  1. Kelas dapat memperluas paling banyak satu kelas abstrak
  2. Kelas abstrak dapat berisi kode
  3. Kelas abstrak dapat mendefinisikan konstanta statis dan instan (final)
  4. Kelas abstrak dapat mendefinisikan variabel instan
  5. Modifikasi kode kelas abstrak yang ada memiliki efek riak pada kelas yang diperluas (pemeliharaan implementasi)
  6. Menambahkan metode baru ke kelas abstrak tidak memiliki efek riak pada kelas yang diperluas
  7. Kelas abstrak dapat mengimplementasikan sebuah antarmuka
  8. Kelas abstrak dapat mengimplementasikan metode privat dan dilindungi

Kelas abstrak harus digunakan untuk implementasi (parsial). Mereka bisa menjadi sarana untuk menahan cara kontrak API harus diterapkan.

Jérôme Verstrynge
sumber
3
Di Java 8 untuk antarmuka # 8, Anda dapat memiliki defaultdan staticmetode juga.
Pengguna Novice
10

Ada banyak jawaban bagus di sini, tetapi saya sering menemukan menggunakan KEDUA antarmuka dan kelas abstrak adalah rute terbaik. Pertimbangkan contoh yang dibuat-buat ini:

Anda adalah pengembang perangkat lunak di bank investasi, dan perlu membangun sistem yang menempatkan pesanan ke pasar. Antarmuka Anda menangkap gagasan paling umum tentang apa yang dilakukan sistem perdagangan ,

1) Trading system places orders
2) Trading system receives acknowledgements

dan dapat ditangkap dalam sebuah antarmuka, ITradeSystem

public interface ITradeSystem{

     public void placeOrder(IOrder order);
     public void ackOrder(IOrder order);

}

Sekarang teknisi yang bekerja di meja penjualan dan di sepanjang lini bisnis lainnya dapat mulai berinteraksi dengan sistem Anda untuk menambahkan fungsionalitas penempatan pesanan ke aplikasi mereka yang ada. Dan Anda bahkan belum mulai membangun! Inilah kekuatan antarmuka.

Jadi Anda melanjutkan dan membangun sistem untuk pedagang saham ; mereka telah mendengar bahwa sistem Anda memiliki fitur untuk menemukan saham murah dan sangat ingin mencobanya! Anda menangkap perilaku ini dalam sebuah metode yang disebut findGoodDeals(), tetapi juga menyadari ada banyak hal berantakan yang terlibat dalam menghubungkan ke pasar. Misalnya, Anda harus membuka SocketChannel,

public class StockTradeSystem implements ITradeSystem{    

    @Override 
    public void placeOrder(IOrder order);
         getMarket().place(order);

    @Override 
    public void ackOrder(IOrder order);
         System.out.println("Order received" + order);    

    private void connectToMarket();
       SocketChannel sock = Socket.open();
       sock.bind(marketAddress); 
       <LOTS MORE MESSY CODE>
    }

    public void findGoodDeals();
       deals = <apply magic wizardry>
       System.out.println("The best stocks to buy are: " + deals);
    }

Implementasi konkret akan memiliki banyak metode berantakan seperti ini connectToMarket(), tetapi findGoodDeals()semua pedagang benar-benar peduli.

Sekarang di sinilah kelas abstrak berperan. Bos Anda memberi tahu Anda bahwa pedagang mata uang juga ingin menggunakan sistem Anda. Dan melihat pasar mata uang, Anda melihat pipa ledeng hampir identik dengan pasar saham. Bahkan, connectToMarket()dapat digunakan kembali secara verbatim untuk menghubungkan ke pasar valuta asing. Namun, findGoodDeals()adalah konsep yang jauh berbeda di arena mata uang. Jadi sebelum Anda memberikan basis kode kepada anak ahli valuta asing di seberang lautan, Anda terlebih dahulu melakukan refaktorisasi ke dalam sebuah abstractkelas, meninggalkanfindGoodDeals()

public abstract class ABCTradeSystem implements ITradeSystem{    

    public abstract void findGoodDeals();

    @Override 
    public void placeOrder(IOrder order);
         getMarket().place(order);

    @Override 
    public void ackOrder(IOrder order);
         System.out.println("Order received" + order);    

    private void connectToMarket();
       SocketChannel sock = Socket.open();
       sock.bind(marketAddress); 
       <LOTS MORE MESSY CODE>
    }

Sistem perdagangan saham Anda menerapkan findGoodDeals()seperti yang telah Anda tentukan,

public class StockTradeSystem extends ABCTradeSystem{    

    public void findGoodDeals();
       deals = <apply magic wizardry>
       System.out.println("The best stocks to buy are: " + deals);
    }

tetapi sekarang bocah ahli FX dapat membangun sistemnya hanya dengan menyediakan implementasi findGoodDeals()untuk mata uang; dia tidak harus menerapkan ulang koneksi soket atau bahkan metode antarmuka!

public class CurrencyTradeSystem extends ABCTradeSystem{    

    public void findGoodDeals();
       ccys = <Genius stuff to find undervalued currencies>
       System.out.println("The best FX spot rates are: " + ccys);
    }

Pemrograman ke antarmuka sangat bermanfaat, tetapi aplikasi serupa sering kali menerapkan ulang metode dengan cara yang hampir identik. Menggunakan kelas abstrak menghindari reimplmentation, sambil mempertahankan kekuatan antarmuka.

Catatan: orang mungkin bertanya-tanya mengapa findGreatDeals()bukan bagian dari antarmuka. Ingat, antarmuka menentukan komponen paling umum dari sistem perdagangan. Insinyur lain mungkin mengembangkan sistem perdagangan yang BENAR-BENAR BERBEDA, di mana mereka tidak peduli tentang menemukan penawaran yang bagus. Antarmuka tersebut menjamin bahwa meja penjualan juga dapat berinteraksi dengan sistem mereka, jadi sebaiknya tidak melibatkan antarmuka Anda dengan konsep aplikasi seperti "penawaran hebat".

Adam Hughes
sumber
6

Mana yang harus Anda gunakan, kelas atau antarmuka abstrak?

Pertimbangkan untuk menggunakan kelas abstrak jika salah satu dari pernyataan berikut berlaku untuk kasus penggunaan Anda:

Anda ingin berbagi kode di antara beberapa kelas yang terkait erat.

Anda berharap bahwa kelas yang memperluas kelas abstrak Anda memiliki banyak metode atau bidang umum, atau memerlukan pengubah akses selain publik (seperti dilindungi dan pribadi).

Anda ingin mendeklarasikan bidang non-statis atau non-final. Ini memungkinkan Anda untuk menentukan metode yang dapat mengakses dan mengubah status objek tempat mereka berada.

Pertimbangkan untuk menggunakan antarmuka jika salah satu dari pernyataan ini berlaku untuk kasus penggunaan Anda:

Anda berharap bahwa kelas yang tidak terkait akan mengimplementasikan antarmuka Anda. Misalnya, antarmuka Comparable dan Cloneable diimplementasikan oleh banyak kelas yang tidak terkait.

Anda ingin menentukan perilaku tipe data tertentu, tetapi tidak peduli tentang siapa yang mengimplementasikan perilakunya.

Anda ingin memanfaatkan multiple inheritance of type.

http://docs.oracle.com/javase/tutorial/java/IandI/abstract.html

Santh
sumber
4

Banyak hal telah banyak berubah dalam tiga tahun terakhir dengan penambahan kemampuan baru untuk antarmuka dengan rilis Java 8.

Dari halaman dokumentasi oracle di antarmuka:

Antarmuka adalah jenis referensi, mirip dengan kelas, yang hanya dapat berisi konstanta, tanda tangan metode, metode default, metode statis , dan jenis bertingkat. Badan metode hanya ada untuk metode default dan metode statis.

Seperti yang Anda kutip dalam pertanyaan Anda, kelas abstrak paling cocok untuk pola metode templat di mana Anda harus membuat kerangka. Antarmuka tidak dapat digunakan di sini.

Satu lagi pertimbangan untuk lebih memilih kelas abstrak daripada antarmuka:

Anda tidak memiliki implementasi di kelas dasar dan hanya sub-kelas yang harus menentukan implementasinya sendiri. Anda memerlukan kelas abstrak sebagai ganti antarmuka karena Anda ingin berbagi status dengan sub-kelas.

Kelas abstrak menetapkan "adalah" hubungan antara kelas terkait dan antarmuka menyediakan "memiliki" kemampuan antara kelas yang tidak terkait .


Mengenai bagian kedua dari pertanyaan Anda, yang valid untuk sebagian besar bahasa pemrograman termasuk java sebelum rilis java-8

Selalu ada trade-off, antarmuka memberi Anda kebebasan berkenaan dengan kelas dasar, kelas abstrak memberi Anda kebebasan untuk menambahkan metode baru nanti. - Erich Gamma

Anda tidak dapat pergi dan mengubah Antarmuka tanpa harus mengubah banyak hal lain dalam kode Anda

Jika Anda lebih suka kelas abstrak untuk antarmuka sebelumnya dengan dua pertimbangan di atas, Anda harus berpikir ulang sekarang karena metode default telah menambahkan kemampuan yang kuat ke antarmuka.

Metode default memungkinkan Anda menambahkan fungsionalitas baru ke antarmuka pustaka Anda dan memastikan kompatibilitas biner dengan kode yang ditulis untuk versi lama antarmuka tersebut.

Untuk memilih salah satunya antara antarmuka dan kelas abstrak, halaman dokumentasi oracle mengutip yang:

Kelas abstrak mirip dengan antarmuka. Anda tidak dapat membuat instance, dan mereka mungkin berisi campuran metode yang dideklarasikan dengan atau tanpa implementasi. Namun, dengan kelas abstrak, Anda dapat mendeklarasikan bidang yang tidak statis dan final, dan menentukan metode konkret publik, dilindungi, dan pribadi.

Dengan antarmuka, semua kolom otomatis menjadi publik, statis, dan final, dan semua metode yang Anda deklarasikan atau tentukan (sebagai metode default) bersifat publik. Selain itu, Anda hanya dapat memperluas satu kelas, apakah itu abstrak atau tidak, sedangkan Anda dapat mengimplementasikan sejumlah antarmuka.

Lihat pertanyaan terkait ini untuk detail lebih lanjut:

Antarmuka vs Kelas Abstrak (OO umum)

Bagaimana seharusnya saya menjelaskan perbedaan antara Antarmuka dan kelas Abstrak?

Singkatnya: Saldo sekarang lebih condong ke antarmuka .

Adakah skenario lain, selain yang disebutkan di atas, di mana secara khusus kita perlu menggunakan kelas abstrak (lihat apakah pola desain metode template secara konseptual hanya didasarkan pada ini)?

Beberapa pola desain menggunakan kelas abstrak (melalui antarmuka) selain dari pola metode Template.

Pola penciptaan:

Abstract_factory_pattern

Pola struktural:

Decorator_pattern

Pola perilaku:

Mediator_pattern

Ravindra babu
sumber
Ini: "Kelas abstrak menetapkan" adalah "hubungan antara kelas terkait dan antarmuka menyediakan" memiliki "kemampuan antara kelas yang tidak terkait."
Gabriel
3

Anda tidak benar. Ada banyak skenario. Tidak mungkin untuk menguranginya menjadi satu aturan 8 kata.

pengguna207421
sumber
1
Kecuali jika Anda tidak jelas seperti; Gunakan antarmuka kapan pun Anda bisa;)
Peter Lawrey
@PeterLawrey Ya, jangan biarkan argumen melingkar memperlambat Anda ;-)
user207421
Ini adalah "stack overflow". ;) Maksud saya adalah jika Anda dapat menggunakan antarmuka yang lebih sederhana, lakukanlah. Jika tidak, Anda tidak punya pilihan selain menggunakan kelas abstrak. Saya tidak melihatnya terlalu rumit.
Peter Lawrey
i think u bisa memberikan ide yang lebih konstruktif. seperti berbicara tentang beberapa skenario representatif /
Adams.H
3

Jawaban terpendeknya adalah, perluas kelas abstrak ketika beberapa fungsi yang Anda cari sudah diterapkan di dalamnya.

Jika Anda mengimplementasikan antarmuka Anda harus mengimplementasikan semua metode. Tetapi untuk kelas abstrak jumlah metode yang perlu Anda implementasikan mungkin lebih sedikit.

Dalam pola desain template harus ada perilaku yang ditentukan. Perilaku ini bergantung pada metode lain yang abstrak. Dengan membuat sub kelas dan mendefinisikan metode-metode tersebut Anda benar-benar mendefinisikan perilaku utama. Perilaku yang mendasari tidak dapat berada di antarmuka karena antarmuka tidak mendefinisikan apa pun, hanya mendeklarasikan. Jadi pola desain template selalu hadir dengan kelas abstrak. Jika Anda ingin menjaga alur perilaku tetap utuh, Anda harus memperluas kelas abstrak tetapi tidak mengganti perilaku utama.

Shiplu Mokaddim
sumber
Referensi tambahan untuk Fungsi Virtual Murni akan menambahkan lebih banyak wawasan tentang Konvergensi Kelas & Antarmuka Abstrak , Pure virtual functions can also be used where the method declarations are being used to define an interface - similar to what the interface keyword in Java explicitly specifies. In such a use, derived classes will supply all implementations. In such a design pattern, the abstract class which serves as an interface will contain only pure virtual functions, but no data members or ordinary methods. Bagian (1/2)
Abhijeet
Bagian (2/2) Divergensi Kelas & Antarmuka Abstrak dijelaskan oleh baris terakhir di atas no data members or ordinary methods[dalam Kelas Abstrak].
Abhijeet
3

Menurut saya, perbedaan dasarnya adalah itu an interface can't contain non abstract methods while an abstract class can. Jadi jika subclass berbagi perilaku yang sama, perilaku ini dapat diimplementasikan di super class dan dengan demikian diwarisi di subclass

Juga saya kutip yang berikut dari buku "desain arsitektur perangkat lunak ppatterns di java"

"Dalam bahasa pemrograman Java, tidak ada dukungan untuk multiple inheritance. Artinya sebuah kelas hanya dapat mewarisi dari satu kelas tunggal. Oleh karena itu, pewarisan harus digunakan hanya jika benar-benar diperlukan. Jika memungkinkan, metode yang menunjukkan perilaku umum harus dideklarasikan dalam bentuk antarmuka Java untuk diimplementasikan oleh kelas pelaksana yang berbeda. Namun antarmuka mengalami keterbatasan sehingga mereka tidak dapat menyediakan implementasi metode. Ini berarti bahwa setiap pelaksana antarmuka harus secara eksplisit mengimplementasikan semua metode yang dideklarasikan dalam sebuah antarmuka, bahkan ketika beberapa di antaranya metode mewakili bagian yang tidak berubah dari fungsionalitas dan memiliki implementasi yang persis sama di semua kelas pelaksana. Hal ini mengarah ke kode yang berlebihan.Contoh berikut menunjukkan bagaimana pola Abstrak Parent Class dapat digunakan dalam kasus seperti itu tanpa memerlukan implementasi metode yang berlebihan. "

pengguna2794921
sumber
2

Kelas abstrak berbeda dari antarmuka dalam dua aspek penting

  • mereka menyediakan implementasi default untuk metode yang dipilih (yang dicakup oleh jawaban Anda)
  • kelas abstrak dapat memiliki status (variabel instan) - jadi ini adalah satu situasi lagi Anda ingin menggunakannya sebagai pengganti antarmuka
Piotr Kochański
sumber
Saya akan menyelesaikan bahwa antarmuka dapat memiliki variabel tetapi secara default final.
Tomasz Mularczyk
1

Ini adalah pertanyaan yang bagus. Keduanya tidak sama tetapi dapat digunakan untuk beberapa alasan yang sama, seperti menulis ulang. Saat membuatnya, yang terbaik adalah menggunakan Antarmuka. Ketika turun ke kelas, itu bagus untuk debugging.

sharonda walker
sumber
0

Abstract classes should be extended when you want to some common behavior to get extended. Kelas super Abstrak akan memiliki perilaku yang sama dan akan menentukan metode abstrak / perilaku spesifik yang harus diterapkan oleh sub kelas.

Interfaces allows you to change the implementation anytime allowing the interface to be intact.

Ramesh PVK
sumber
0

Ini pemahaman saya, semoga ini membantu

Kelas abstrak:

  1. Dapat memiliki variabel anggota yang diwariskan (tidak dapat dilakukan di antarmuka)
  2. Dapat memiliki konstruktor (antarmuka tidak dapat)
  3. Metodenya dapat memiliki visibilitas apa pun (misalnya: pribadi, dilindungi, dll - sedangkan semua metode antarmuka bersifat publik)
  4. Dapat memiliki metode yang ditentukan (metode dengan implementasi)

Antarmuka:

  1. Dapat memiliki variabel, tetapi semuanya adalah variabel final statis publik
    • nilai konstan yang tidak pernah berubah dengan lingkup statis
    • variabel non-statis memerlukan sebuah instance, dan Anda tidak dapat membuat instance antarmuka
  2. Semua metode abstrak (tidak ada kode dalam metode abstrak)
    • semua kode harus benar-benar ditulis di kelas yang mengimplementasikan antarmuka tertentu
zozep
sumber
0

Penggunaan abstrak dan antarmuka:

Satu memiliki "Hubungan-Is-A" dan yang lainnya memiliki "Hubungan-Has-A"

Properti default telah diatur dalam abstrak dan properti tambahan dapat diekspresikan melalui antarmuka.

Contoh: -> Dalam diri manusia kita memiliki beberapa properti default yaitu makan, tidur, dll. Tetapi jika ada yang memiliki aktivitas kurikuler lain seperti berenang, bermain, dll, itu dapat diekspresikan oleh Interface.

pengguna7439667
sumber