Seseorang juga bisa melakukan raise NotImplementedError()
di dalam metode anak dari @abstractmethod
metode kelas dasar berdekorasi.
Bayangkan menulis skrip kontrol untuk keluarga modul pengukuran (perangkat fisik). Fungsionalitas setiap modul didefinisikan secara sempit, hanya menerapkan satu fungsi khusus: satu dapat berupa array relai, yang lain DAC atau ADC multi-saluran, yang lain ammeter, dll.
Banyak dari perintah tingkat rendah yang digunakan akan dibagikan antar modul misalnya untuk membaca nomor ID mereka atau untuk mengirim perintah kepada mereka. Mari kita lihat apa yang kita miliki saat ini:
Kelas Dasar
from abc import ABC, abstractmethod
class Generic(ABC):
''' Base class for all measurement modules. '''
def __init__(self):
def _read_ID(self):
def _send_command(self, value):
Kata Kerja Bersama
Kami kemudian menyadari bahwa banyak dari kata kerja perintah khusus modul dan, oleh karena itu, logika antarmukanya juga digunakan bersama. Berikut adalah 3 kata kerja berbeda yang artinya sudah cukup jelas mengingat sejumlah modul target.
get(channel)
relai: nyalakan / matikan status relaichannel
DAC: mendapatkan output yang tegangan padachannel
ADC: mendapatkan masukan tegangan padachannel
enable(channel)
relai: aktifkan penggunaan relaichannel
DAC: aktifkan penggunaan saluran keluaranchannel
ADC: aktifkan penggunaan saluran inputchannel
set(channel)
relai: nyalakan channel
/ matikan relai
DAC: setel tegangan keluaranchannel
ADC: hmm ... tidak logis datang ke pikiran.
Kata Kerja Bersama Menjadi Kata Kerja yang Dipaksakan
Saya berpendapat bahwa ada alasan kuat untuk kata kerja di atas untuk dibagikan di seluruh modul karena kita melihat bahwa maknanya terbukti untuk masing-masing modul. Saya akan terus menulis kelas dasar saya Generic
seperti ini:
class Generic(ABC):
@abstractmethod
def get(self, channel):
pass
@abstractmethod
def enable(self, channel):
pass
@abstractmethod
def set(self, channel):
pass
Subkelas
Kita sekarang tahu bahwa semua subclass kita harus mendefinisikan metode ini. Mari kita lihat seperti apa modul ADC:
class ADC(Generic):
def __init__(self):
super().__init__()
def get(self, channel):
def enable(self, channel):
Anda sekarang mungkin bertanya-tanya:
Tetapi ini tidak akan berfungsi untuk modul ADC karena set
tidak masuk akal di sana karena kita baru saja melihat ini di atas!
Anda benar: tidak mengimplementasikan set
bukanlah pilihan karena Python kemudian akan mengaktifkan kesalahan di bawah ini ketika Anda mencoba membuat instance objek ADC Anda.
TypeError: Can't instantiate abstract class 'ADC' with abstract methods 'set'
Jadi, Anda harus menerapkan sesuatu, karena kami membuat set
sebuah ditegakkan kata kerja (alias '@abstractmethod'), yang dibagi oleh dua modul lain tetapi, pada saat yang sama, Anda juga harus tidak melaksanakan apa-apa karena
set
tidak masuk akal untuk modul tertentu.
NotImplementedError to the Rescue
Dengan menyelesaikan kelas ADC seperti ini:
class ADC(Generic):
def set(self, channel):
raise NotImplementedError("Can't use 'set' on an ADC!")
Anda melakukan tiga hal yang sangat baik sekaligus:
- Anda melindungi pengguna dari kesalahan mengeluarkan perintah ('set') yang tidak (dan tidak boleh!) Diimplementasikan untuk modul ini.
- Anda memberi tahu mereka secara eksplisit apa masalahnya (lihat tautan TemporalWolf tentang 'Bare pengecualian' mengapa ini penting)
- Anda melindungi implementasi dari semua modul lainnya yang kata kerjanya
masuk akal. Yaitu Anda memastikan bahwa mereka modul yang kata kerja ini melakukan make akal akan menerapkan metode ini dan bahwa mereka akan melakukannya dengan menggunakan persis kata kerja ini dan tidak beberapa nama ad-hoc lainnya.