2011-11-03 13 views
16

में प्रत्यक्ष तत्कालता से कक्षा को रोकना मेरे पास एक ऐसी विधि है जिसमें अन्य विधियां हैं जिन्हें केवल उप-वर्गों में परिभाषित किया गया है। यही कारण है कि, जब मैं अपनी सुपर क्लास का उदाहरण बनाता हूं और अपनी विधि को कॉल करता हूं, तो यह विधि नहीं ढूंढ सकता है और एक त्रुटि उठाता है।पायथन

यहाँ एक उदाहरण है:

class SuperClass(object): 

    def method_one(self): 
    value = self.subclass_method() 
    print value 


class SubClassOne(SuperClass): 

    def subclass_method(self): 
    return 'subclass 1' 


class SubClassTwo(SuperClass): 

    def subclass_method(self): 
    return 'nubclass 2' 


s1 = SubClassOne() 
s1.method_one() 

s2 = SubClassTwo() 
s2.method_one() 

c = SuperClass() 
c.method_one() 

# Results: 
# subclass 1 
# nubclass 2 
# Traceback (most recent call last): 
# File "abst.py", line 28, in <module> 
#  c.method_one() 
# File "abst.py", line 4, in method_one 
#  value = self.subclass_method() 
# AttributeError: 'SuperClass' object has no attribute 'subclass_method' 

मैं init सुपर वर्ग के बदल रहा है और, ऑब्जेक्ट का प्रकार सत्यापित करें जब एक नया उदाहरण बन जाता है के बारे में सोच रहा था। यदि वस्तु सुपर क्लास से संबंधित है तो एक त्रुटि उठाएं। हालांकि, मुझे यकीन नहीं है कि यह करने का पाइथोनिक तरीका है या नहीं।

कोई सिफारिशें?

+3

पाइथोनिक तरीका अच्छी प्रलेखन लिखना है कि आपकी कक्षा का उपयोग कैसे किया जाए। – yak

+2

@chown: यह वास्तव में सी ++ में अक्सर किया जाता है। वह क्या कर रहा है अनिवार्य रूप से आभासी तरीकों को बुला रहा है। उनके साथ स्वाभाविक रूप से गलत कुछ भी नहीं है, अगर वे समस्या का उचित समाधान हैं। – rossipedia

+1

मैं इस बात से सहमत हूं कि यह बहुत पाइथनिक नहीं है – rossipedia

उत्तर

9

आप सार बेस क्लासेस के बारे में बात कर रहे हैं, और पायथन भाषा उन्हें मूल रूप से समर्थन नहीं देती है।

हालांकि, मानक पुस्तकालय में, एक मॉड्यूल है जिसका उपयोग आप सहायता के लिए कर सकते हैं। abc दस्तावेज़ीकरण देखें।

+1

असल में पाइथन पर इसे लागू करने के कई और तरीके हैं, लेकिन मैं सिर्फ एबीसी मॉड्यूल आयात करने जा रहा हूं और अपनी कक्षा को एक अमूर्त वर्ग के रूप में सेट कर रहा हूं। मैंने देखा कि मेरी कक्षा अमूर्त है, फिर भी मैं इसमें विधियों को लागू कर सकता हूं, जो बहुत अच्छा है। – mohi666

16

आपका दृष्टिकोण एक विशिष्ट framework pattern है।

type(self) is not SuperClass सत्यापित करने के लिए __init__ का उपयोग करना यह सुनिश्चित करने का एक उचित तरीका है कि सुपर क्लास को तुरंत चालू नहीं किया गया है।

अन्य आम दृष्टिकोण स्टब विधियों को प्रदान करना है जो raise NotImplementedError कहलाते हैं। यह अधिक विश्वसनीय है क्योंकि यह भी मान्य करता है कि उप-वर्गों ने अपेक्षित तरीकों को ओवरराइड कर दिया है।

7

यह मैं क्या कर सकता है:

class SuperClass(object): 
    def __init__(self): 
     if type(self) == SuperClass: 
      raise Exception("<SuperClass> must be subclassed.") 
     # assert(type(self) == SuperClass) 

class SubClass(SuperClass): 
    def __init__(self): 
     SuperClass.__init__(self) 

subC = SubClassOne() 
supC = SuperClass() # This line should throw an exception 

जब रन (अपवाद फेंक दिया जाता है!):

[ 18:32 [email protected] ~/so/python ]$ ./preventing-direct-instantiation.py 
Traceback (most recent call last): 
    File "./preventing-direct-instantiation.py", line 15, in <module> 
    supC = SuperClass() 
    File "./preventing-direct-instantiation.py", line 7, in __init__ 
    raise Exception("<SuperClass> must be subclassed.") 
Exception: <SuperClass> must be subclassed. 

(टिप्पणियों से) संपादित करें:

[ 20:13 [email protected] ~/SO/python ]$ cat preventing-direct-instantiation.py 
#!/usr/bin/python 

class SuperClass(object): 
    def __init__(self): 
     if type(self) == SuperClass: 
      raise Exception("<SuperClass> must be subclassed.") 

class SubClassOne(SuperClass): 
    def __init__(self): 
     SuperClass.__init__(self) 

class SubSubClass(SubClassOne): 
    def __init__(self): 
     SubClassOne.__init__(self) 

class SubClassTwo(SubClassOne, SuperClass): 
    def __init__(self): 
     SubClassOne.__init__(self) 
     SuperClass.__init__(self) 

subC = SubClassOne() 

try: 
    supC = SuperClass() 
except Exception, e: 
    print "FAILED: supC = SuperClass() - %s" % e 
else: 
    print "SUCCESS: supC = SuperClass()" 

try: 
    subSubC = SubSubClass() 
except Exception, e: 
    print "FAILED: subSubC = SubSubClass() - %s" % e 
else: 
    print "SUCCESS: subSubC = SubSubClass()" 

try: 
    subC2 = SubClassTwo() 
except Exception, e: 
    print "FAILED: subC2 = SubClassTwo() - %s" % e 
else: 
    print "SUCCESS: subC2 = SubClassTwo()" 

प्रिंट:

[ 20:12 [email protected] ~/SO/python ]$ ./preventing-direct-instantiation.py 
FAILED: supC = SuperClass() - <SuperClass> must be subclassed. 
SUCCESS: subSubC = SubSubClass() 
SUCCESS: subC2 = SubClassTwo() 
+0

यह नहीं कह रहा कि यह बहुत अच्छा नहीं है, लेकिन मुझे लगता है कि यह दिखाता है कि आपको इस तरह की चीज करने की कोशिश क्यों नहीं करनी चाहिए। मुझे यकीन है कि दोनों उदाहरण एकाधिक विरासत के साथ विफल हो जाते हैं। – sdolan

+0

@ एसडोलन मैंने अभी परीक्षण किया है, और यह वास्तव में 'वर्ग सबसब क्लास (सबक्लासऑन) के साथ काम करता है:' और 'subclassOne .__ init __ (self)' को अपने '__init__' से कॉल करना! – chown

+0

आह बहुत अच्छा है। उस अद्यतन को बनाने के लिए धन्यवाद। – sdolan

22

मैं बेस क्लास में __new__() ओवरराइड कर दूंगा और बेस क्लास होने पर बस तत्काल विफल हो जाऊंगा।

class BaseClass(object): 

    def __new__(cls, *args, **kwargs): 
     if cls is BaseClass: 
      raise TypeError("base class may not be instantiated") 
     return object.__new__(cls, *args, **kwargs) 

यह चिंताओं एक छोटे से __init__() में यह होने की तुलना में बेहतर अलग करती है, और "तेजी से विफल रहता है।"

+2

'abc' मॉड्यूल शायद 90% मामलों के लिए सही है, लेकिन यह तकनीक कुछ अन्य लोगों में उपयोगी है। मुझे कुछ सामना करना पड़ा है: 1.) आप एक पुन: प्रयोज्य मिक्स्ड क्लास चाहते हैं लेकिन वास्तव में इसमें कोई सार तत्व नहीं है, इसलिए 'एबीसीएमटा' इसे तत्काल होने से नहीं रोकेगा; 2.) आप एक "आधार" वर्ग या मिश्रण को परिभाषित कर रहे हैं जो वास्तव में कुछ और subclasses, लेकिन आप नहीं चाहते हैं कि यह सीधे तत्काल हो। – ches

+0

यह वास्तव में बहुत उपयोगी है। मैं यह जोड़ना चाहता हूं कि यदि बेस क्लास ने व्हायरबेस क्लास को विरासत में मिला है, तो ऑब्जेक्ट के बजाय VeryBaseClass .__ नया __() वापस करें .__ new __() – cfchou