Apa perbedaan antara kelas abstrak dan antarmuka dalam Python?
559
Apa perbedaan antara kelas abstrak dan antarmuka dalam Python?
Apa yang akan Anda lihat kadang-kadang adalah sebagai berikut:
class Abstract1( object ):
"""Some description that tells you it's abstract,
often listing the methods you're expected to supply."""
def aMethod( self ):
raise NotImplementedError( "Should have implemented this" )
Karena Python tidak memiliki (dan tidak perlu) kontrak Antarmuka formal, perbedaan gaya Java antara abstraksi dan antarmuka tidak ada. Jika seseorang melalui upaya untuk mendefinisikan antarmuka formal, itu juga akan menjadi kelas abstrak. Satu-satunya perbedaan adalah dalam maksud yang dinyatakan dalam dokumen.
Dan perbedaan antara abstrak dan antarmuka adalah hal yang menarik ketika Anda mengetik bebek.
Java menggunakan antarmuka karena tidak memiliki banyak warisan.
Karena Python memiliki banyak pewarisan, Anda juga dapat melihat sesuatu seperti ini
class SomeAbstraction( object ):
pass # lots of stuff - but missing something
class Mixin1( object ):
def something( self ):
pass # one implementation
class Mixin2( object ):
def something( self ):
pass # another
class Concrete1( SomeAbstraction, Mixin1 ):
pass
class Concrete2( SomeAbstraction, Mixin2 ):
pass
Ini menggunakan semacam superclass abstrak dengan mixin untuk membuat subkelas beton yang terpisah.
NotImplementedError("Class %s doesn't implement aMethod()" % (self.__class__.__name__))
adalah pesan kesalahan yang lebih informatif :)Antarmuka, untuk suatu objek, adalah seperangkat metode dan atribut pada objek itu.
Dengan Python, kita bisa menggunakan kelas dasar abstrak untuk mendefinisikan dan menjalankan antarmuka.
Menggunakan Kelas Basis Abstrak
Sebagai contoh, katakanlah kita ingin menggunakan salah satu kelas dasar abstrak dari
collections
modul:Jika kita mencoba menggunakannya, kita mendapatkan
TypeError
karena kelas yang kita buat tidak mendukung perilaku set yang diharapkan:Jadi kita dituntut untuk menerapkan di setidaknya
__contains__
,__iter__
, dan__len__
. Mari kita gunakan contoh implementasi ini dari dokumentasi :Implementasi: Membuat Kelas Basis Abstrak
Kita dapat membuat Kelas Dasar Abstrak kita sendiri dengan mengatur metaclass ke
abc.ABCMeta
dan menggunakanabc.abstractmethod
dekorator pada metode yang relevan. Metaclass akan menambahkan fungsi-fungsi yang didekorasi ke__abstractmethods__
atribut, mencegah instantiation hingga didefinisikan.Sebagai contoh, "effable" didefinisikan sebagai sesuatu yang dapat diekspresikan dalam kata-kata. Katakanlah kita ingin mendefinisikan kelas dasar abstrak yang efektif, dengan Python 2:
Atau dengan Python 3, dengan sedikit perubahan dalam deklarasi metaclass:
Sekarang jika kita mencoba membuat objek yang efektif tanpa mengimplementasikan antarmuka:
dan berusaha untuk instantiate:
Kami diberitahu bahwa kami belum menyelesaikan pekerjaan.
Sekarang jika kami mematuhi dengan menyediakan antarmuka yang diharapkan:
kita kemudian dapat menggunakan versi konkret dari kelas yang berasal dari abstrak:
Ada hal-hal lain yang bisa kita lakukan dengan ini, seperti mendaftar subkelas virtual yang sudah mengimplementasikan antarmuka ini, tapi saya pikir itu di luar cakupan pertanyaan ini. Namun, metode lain yang diperlihatkan di sini harus mengadaptasi metode ini menggunakan
abc
modul untuk melakukannya.Kesimpulan
Kami telah menunjukkan bahwa pembuatan Kelas Basis Abstrak mendefinisikan antarmuka untuk objek khusus dalam Python.
sumber
Python> = 2.6 memiliki Kelas Basis Abstrak .
Ada juga modul Zope Interface , yang digunakan oleh proyek di luar zope, seperti twisted. Saya tidak terlalu mengenalnya, tetapi ada halaman wiki di sini yang mungkin membantu.
Secara umum, Anda tidak memerlukan konsep kelas abstrak, atau antarmuka dalam python (diedit - lihat jawaban S.Lott untuk detailnya).
sumber
Python tidak benar-benar memiliki konsep apa pun.
Ini menggunakan mengetik bebek, yang menghilangkan kebutuhan untuk antarmuka (setidaknya untuk komputer :-))
Python <= 2.5: Kelas dasar jelas ada, tetapi tidak ada cara eksplisit untuk menandai metode sebagai 'virtual murni', sehingga kelas tidak benar-benar abstrak.
Python> = 2.6: Kelas dasar abstrak memang ada ( http://docs.python.org/library/abc.html ). Dan memungkinkan Anda untuk menentukan metode yang harus diimplementasikan dalam subkelas. Saya tidak terlalu suka dengan sintaks, tetapi fitur itu ada. Sebagian besar waktu mungkin lebih baik menggunakan itik mengetik dari sisi klien 'menggunakan'.
sumber
Dengan cara yang lebih mendasar untuk menjelaskan: Antarmuka adalah semacam panci muffin kosong. Ini adalah file kelas dengan sekumpulan definisi metode yang tidak memiliki kode.
Kelas abstrak adalah hal yang sama, tetapi tidak semua fungsi harus kosong. Beberapa dapat memiliki kode. Ini tidak sepenuhnya kosong.
Mengapa membedakan: Tidak ada banyak perbedaan praktis dalam Python, tetapi pada tingkat perencanaan untuk proyek besar, bisa lebih umum untuk berbicara tentang antarmuka, karena tidak ada kode. Terutama jika Anda bekerja dengan programmer Java yang terbiasa dengan istilah tersebut.
sumber
Secara umum, antarmuka hanya digunakan dalam bahasa yang menggunakan model kelas pewarisan tunggal. Dalam bahasa pewarisan tunggal ini, antarmuka biasanya digunakan jika kelas mana pun dapat menggunakan metode atau serangkaian metode tertentu. Juga dalam bahasa pewarisan-tunggal ini, kelas-kelas abstrak digunakan untuk menentukan variabel kelas selain dari tidak ada atau lebih metode, atau untuk mengeksploitasi model pewarisan tunggal untuk membatasi rentang kelas yang dapat menggunakan serangkaian metode.
Bahasa yang mendukung model multiple-inheritance cenderung hanya menggunakan kelas atau kelas dasar abstrak dan bukan antarmuka. Karena Python mendukung multiple inheritance, ia tidak menggunakan antarmuka dan Anda ingin menggunakan kelas dasar atau kelas dasar abstrak.
http://docs.python.org/library/abc.html
sumber
Kelas abstrak adalah kelas yang berisi satu atau lebih metode abstrak. Seiring dengan metode abstrak, kelas abstrak dapat memiliki metode statis, kelas dan contoh. Tetapi dalam hal antarmuka, itu hanya akan memiliki metode abstrak bukan yang lain. Oleh karena itu tidak diwajibkan untuk mewarisi kelas abstrak tetapi wajib untuk mewarisi antarmuka.
sumber
Untuk kelengkapan, kita harus menyebutkan PEP3119 di mana ABC diperkenalkan dan dibandingkan dengan antarmuka, dan Talin asli komentar .
Kelas abstrak bukanlah antarmuka yang sempurna:
Tetapi jika Anda mempertimbangkan untuk menuliskannya dengan cara Anda sendiri:
Anda akan dengan cepat menyadari bahwa Anda sedang menciptakan roda untuk akhirnya mencapainya
abc.ABCMeta
abc.ABCMeta
diusulkan sebagai tambahan yang berguna dari fungsi antarmuka yang hilang, dan itu cukup adil dalam bahasa seperti python.Tentu saja, itu dapat ditingkatkan lebih baik saat menulis versi 3, dan menambahkan sintaks baru dan konsep antarmuka yang tidak dapat diubah ...
Kesimpulan:
sumber