นอกจากนี้เรายังสามารถทำraise NotImplementedError()
ภายในเมธอดลูกของ @abstractmethod
เมธอดคลาสฐานที่ได้รับการตกแต่ง
ลองนึกภาพการเขียนสคริปต์ควบคุมสำหรับกลุ่มโมดูลการวัด (อุปกรณ์ทางกายภาพ) ฟังก์ชันการทำงานของแต่ละโมดูลมีการกำหนดไว้อย่างแคบโดยใช้ฟังก์ชันเฉพาะหนึ่งฟังก์ชัน: หนึ่งอาจเป็นอาร์เรย์ของรีเลย์อีกอันคือ DAC หรือ ADC แบบหลายช่องสัญญาณแอมป์มิเตอร์อื่น ๆ เป็นต้น
คำสั่งระดับต่ำที่ใช้อยู่ส่วนใหญ่จะใช้ร่วมกันระหว่างโมดูลเช่นเพื่ออ่านหมายเลข ID หรือส่งคำสั่งไปให้ มาดูกันว่าเรามีอะไรบ้าง ณ จุดนี้:
คลาสพื้นฐาน
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):
กริยาที่ใช้ร่วมกัน
จากนั้นเราตระหนักดีว่าคำกริยาคำสั่งเฉพาะโมดูลส่วนใหญ่จึงมีการแชร์ตรรกะของอินเทอร์เฟซของพวกเขาด้วย ต่อไปนี้เป็นคำกริยาที่แตกต่างกัน 3 คำซึ่งมีความหมายอธิบายได้ด้วยตนเองโดยพิจารณาจากโมดูลเป้าหมายจำนวนหนึ่ง
get(channel)
รีเลย์:รับสถานะเปิด / ปิดของรีเลย์channel
DAC:เปิดแรงดันเอาต์พุตchannel
ADC:เปิดแรงดันไฟฟ้าเข้าchannel
enable(channel)
รีเลย์:เปิดใช้งานรีเลย์channel
DAC:เปิดใช้งานช่องสัญญาณเอาต์พุตบนchannel
ADC:เปิดใช้งานช่องสัญญาณเข้าบนchannel
set(channel)
รีเลย์:ตั้งค่ารีเลย์channel
เปิด / ปิด
DAC:ตั้งค่าแรงดันเอาต์พุตเป็นเปิดchannel
ADC:อืม ... ไม่มีเหตุผลอะไรในใจ
คำกริยาที่ใช้ร่วมกันกลายเป็นคำกริยาบังคับ
ฉันขอยืนยันว่ามีกรณีที่ชัดเจนสำหรับคำกริยาข้างต้นที่จะใช้ร่วมกันในโมดูลเนื่องจากเราเห็นว่าความหมายของพวกเขาชัดเจนสำหรับแต่ละคำกริยา ฉันจะเขียนคลาสพื้นฐานของฉันต่อไปGeneric
ดังนี้:
class Generic(ABC):
@abstractmethod
def get(self, channel):
pass
@abstractmethod
def enable(self, channel):
pass
@abstractmethod
def set(self, channel):
pass
คลาสย่อย
ตอนนี้เรารู้แล้วว่าคลาสย่อยของเราทุกคนจะต้องกำหนดวิธีการเหล่านี้ มาดูกันว่าโมดูล ADC จะเป็นอย่างไร:
class ADC(Generic):
def __init__(self):
super().__init__()
def get(self, channel):
def enable(self, channel):
ตอนนี้คุณอาจสงสัยว่า:
แต่สิ่งนี้จะใช้ไม่ได้กับโมดูลADCเนื่องจากset
ไม่สมเหตุสมผลอย่างที่เราเห็นข้างต้น!
คุณพูดถูก: การไม่ใช้งานset
ไม่ใช่ตัวเลือกเนื่องจาก Python จะเริ่มต้นข้อผิดพลาดด้านล่างเมื่อคุณพยายามสร้างอินสแตนซ์วัตถุ ADC ของคุณ
TypeError: Can't instantiate abstract class 'ADC' with abstract methods 'set'
ดังนั้นคุณจะต้องดำเนินการบางสิ่งบางอย่างเพราะเราทำบังคับใช้คำกริยา (aka '@abstractmethod') ซึ่งจะใช้ร่วมกันโดยสองโมดูลอื่น ๆ แต่ในเวลาเดียวกันคุณต้องยังไม่ได้ดำเนินการอะไร
ไม่ได้ทำให้รู้สึกสำหรับโมดูลนี้โดยเฉพาะset
set
NotImplementedError เพื่อช่วยเหลือ
เมื่อจบคลาส ADC ดังนี้:
class ADC(Generic):
def set(self, channel):
raise NotImplementedError("Can't use 'set' on an ADC!")
คุณกำลังทำสิ่งที่ดีสามอย่างพร้อมกัน:
- คุณกำลังปกป้องผู้ใช้จากการออกคำสั่ง ('set') โดยไม่ถูกต้องซึ่งไม่ได้ใช้ (และไม่ควร!) สำหรับโมดูลนี้
- คุณกำลังบอกพวกเขาอย่างชัดเจนว่าปัญหาคืออะไร (ดูลิงก์ของ TemporalWolf เกี่ยวกับ 'ข้อยกเว้น' ว่าเหตุใดจึงสำคัญ)
- คุณกำลังปกป้องการใช้งานโมดูลอื่น ๆ ทั้งหมดซึ่งคำกริยาที่บังคับใช้
นั้นมีเหตุผล คือคุณมั่นใจได้ว่าโมดูลผู้ที่กริยาเหล่านี้ทำให้ความรู้สึกที่จะใช้วิธีการเหล่านี้และว่าพวกเขาจะทำได้โดยใช้คำกริยาว่าเหล่านี้และไม่บางชื่อเฉพาะกิจอื่น ๆ