একটি শিশু- শৃঙ্খলাবদ্ধ বেস ক্লাস পদ্ধতিতে শিশু পদ্ধতির raise NotImplementedError()
অভ্যন্তরেও একটি করতে পারে @abstractmethod
।
পরিমাপ মডিউল (শারীরিক ডিভাইস) এর পরিবারের জন্য একটি নিয়ন্ত্রণ স্ক্রিপ্ট লেখার কল্পনা করুন। প্রতিটি মডিউলটির কার্যকারিতা সংক্ষিপ্তভাবে সংজ্ঞায়িত করা হয়, কেবল একটি ডেডিকেটেড ফাংশন বাস্তবায়ন করে: একটি রিলে অ্যারের হতে পারে, অন্যটি একটি মাল্টি-চ্যানেল ডিএসি বা এডিসি, অন্য একটি এমমিটার ইত্যাদি could
ব্যবহৃত নিম্ন-স্তরের কমান্ডগুলির বেশিরভাগ মডিউলগুলির মধ্যে ভাগ করা হবে উদাহরণস্বরূপ তাদের আইডি নম্বরগুলি পড়তে বা তাদের কাছে একটি আদেশ প্রেরণ করার জন্য। এই মুহুর্তে আমাদের কী আছে তা দেখুন:
বেস ক্লাস
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
ড্যাক: পেতে আউটপুট উপর ভোল্টেজchannel
এডিসি: পেতে ইনপুট উপর ভোল্টেজchannel
enable(channel)
রিলে: রিলে ব্যবহার সক্ষম করুনchannel
ড্যাক: চালু আউটপুট চ্যানেলের ব্যবহার সক্ষম করুনchannel
এডিসি: ইনপুট চ্যানেলটি চালু করতে সক্ষম করুনchannel
set(channel)
রিলে: রিলে channel
চালু / বন্ধ করুন
ড্যাক: সেট আউটপুট উপর ভোল্টেজchannel
এডিসি: হুম ... যৌক্তিক কিছু মনে আসে না।
ভাগ করা ক্রিয়াগুলি কার্যকর ক্রিয়া হয়ে ওঠে
আমি যুক্তি দিয়েছি যে উপরোক্ত ক্রিয়াগুলি মডিউলগুলিতে ভাগ করার জন্য একটি শক্তিশালী কেস রয়েছে কারণ আমরা দেখেছি যে তাদের প্রতিটিটির প্রতিটির অর্থ স্পষ্ট। আমি আমার বেস ক্লাসটি 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):
আপনি এখন ভাবছেন:
তবে এটি এডিসি মডিউলের জন্য কাজ করবে না set
কারণ সেখানে এটি কোনও তাত্পর্যপূর্ণ নয় কারণ আমরা কেবল এটি উপরে দেখেছি!
আপনি ঠিক বলেছেন: বাস্তবায়ন set
না করা কোনও বিকল্প নয় কারণ পাইথন তারপরে নীচে ত্রুটিটি ছড়িয়ে দেবে যখন আপনি আপনার এডিসি অবজেক্টটি ইনস্ট্যান্ট করার চেষ্টা করেছিলেন।
TypeError: Can't instantiate abstract class 'ADC' with abstract methods 'set'
সুতরাং আপনাকে অবশ্যই কিছু বাস্তবায়ন করতে হবে, কারণ আমরা set
একটি প্রয়োগকৃত ক্রিয়া তৈরি করেছি (ওরফে '@stadmemerod'), যা অন্য দুটি মডিউল দ্বারা ভাগ করা হয় তবে একই সময়ে, আপনাকে অবশ্যই set
কোনও কিছু প্রয়োগ
করতে হবে না কারণ এই বিশেষ মডিউলটির কোনও অর্থ হয় না।
NotImplementedError the Rescue
এডিসি ক্লাস এভাবে শেষ করে:
class ADC(Generic):
def set(self, channel):
raise NotImplementedError("Can't use 'set' on an ADC!")
আপনি একবারে তিনটি খুব ভাল কাজ করছেন:
- আপনি কোনও ব্যবহারকারীকে ভুল করে কোনও কমান্ড ('সেট') জারি করা থেকে রক্ষা করছেন যা এই মডিউলের জন্য প্রয়োগ করা হয়নি (এবং হওয়া উচিত নয়)।
- সমস্যাটি কী তা আপনি তাদের স্পষ্টভাবে বলছেন (কেন এটি গুরুত্বপূর্ণ তা সম্পর্কে 'বেয়ার ব্যতিক্রমগুলি' সম্পর্কে টেম্পোরাল ওল্ফের লিঙ্কটি দেখুন)
- আপনি অন্যান্য সমস্ত মডিউলগুলির বাস্তবায়ন রক্ষা করছেন যার জন্য প্রয়োগকৃত ক্রিয়াগুলি
বোঝায়। অর্থাত আপনি নিশ্চিত করুন যে মডিউলের যার জন্য এই ক্রিয়াগুলো না জানার এই পদ্ধতি বাস্তবায়ন করবে এবং যে তারা ঠিক এই ক্রিয়াগুলো ব্যবহার তাই করতে হবে এবং কিছু অন্যান্য অ্যাড-হক নাম থাকবে না।