Seperti yang dijelaskan dalam jawaban lain, ya Anda bisa menggunakan kelas abstrak di Python menggunakan abc
modul . Di bawah ini saya memberikan contoh aktual menggunakan abstrak @classmethod
, @property
dan @abstractmethod
(menggunakan Python 3.6+). Bagi saya biasanya lebih mudah untuk memulai dengan contoh-contoh yang saya dapat dengan mudah menyalin & menempel; Saya harap jawaban ini juga bermanfaat bagi orang lain.
Pertama mari kita membuat kelas dasar yang disebut Base
:
from abc import ABC, abstractmethod
class Base(ABC):
@classmethod
@abstractmethod
def from_dict(cls, d):
pass
@property
@abstractmethod
def prop1(self):
pass
@property
@abstractmethod
def prop2(self):
pass
@prop2.setter
@abstractmethod
def prop2(self, val):
pass
@abstractmethod
def do_stuff(self):
pass
Base
Kelas kami akan selalu memiliki a from_dict
classmethod
, a property
prop1
(yang hanya baca) dan a property
prop2
(yang juga dapat diatur) serta fungsi yang disebut do_stuff
. Apa pun kelas yang sekarang dibangun berdasarkan Base
harus menerapkan semua ini untuk metode / properti. Harap dicatat bahwa untuk metode menjadi abstrak, diperlukan dua dekorator - classmethod
dan abstrak property
.
Sekarang kita bisa membuat kelas A
seperti ini:
class A(Base):
def __init__(self, name, val1, val2):
self.name = name
self.__val1 = val1
self._val2 = val2
@classmethod
def from_dict(cls, d):
name = d['name']
val1 = d['val1']
val2 = d['val2']
return cls(name, val1, val2)
@property
def prop1(self):
return self.__val1
@property
def prop2(self):
return self._val2
@prop2.setter
def prop2(self, value):
self._val2 = value
def do_stuff(self):
print('juhu!')
def i_am_not_abstract(self):
print('I can be customized')
Semua metode / properti yang diperlukan diimplementasikan dan kami - tentu saja - juga dapat menambahkan fungsi tambahan yang bukan bagian dari Base
(di sini i_am_not_abstract
:).
Sekarang kita bisa melakukan:
a1 = A('dummy', 10, 'stuff')
a2 = A.from_dict({'name': 'from_d', 'val1': 20, 'val2': 'stuff'})
a1.prop1
# prints 10
a1.prop2
# prints 'stuff'
Seperti yang diinginkan, kami tidak dapat mengatur prop1
:
a.prop1 = 100
akan kembali
AttributeError: tidak dapat mengatur atribut
from_dict
Metode kami juga berfungsi dengan baik:
a2.prop1
# prints 20
Jika sekarang kita mendefinisikan kelas kedua B
seperti ini:
class B(Base):
def __init__(self, name):
self.name = name
@property
def prop1(self):
return self.name
dan mencoba untuk instantiate objek seperti ini:
b = B('iwillfail')
kami akan mendapatkan kesalahan
TypeError: Tidak dapat membuat instance kelas abstrak B dengan metode abstrak do_stuff, from_dict, prop2
daftar semua hal yang didefinisikan di Base
mana kami tidak menerapkannya B
.