2010-10-23 9 views
9

मैं रूबी के लिए नया हूं। एक साधारण उदाहरण, मुझे क्या चाहिए:रुबी में अमूर्त कक्षाओं के विकल्प?

class Animal 
    abstract eat() 

class Cat < Animal 
    eat(): 
    implementation 

class Dog < Animal 
    eat(): 
    implementation 

दूसरे शब्दों में, जानवरों को बढ़ाने वाले सभी वर्गों के लिए खाने() विधि की आवश्यकता होनी चाहिए।

जावा में मैं केवल एक अमूर्त वर्ग का उपयोग करता हूं, लेकिन कुछ शोध करने के बाद मुझे पता चला कि बहुत से लोग रूबी में इसका उपयोग नहीं करते हैं और इसके बजाय मिश्रित/मॉड्यूल की सिफारिश की जाती है।

हालांकि, मुझे समझ में नहीं आता है, अगर मॉड्यूल केवल अतिरिक्त तरीकों को शामिल करने से अधिक कर सकता है। सटीक होने के लिए, मॉड्यूल कक्षाओं के लिए आवश्यकताओं को निर्धारित कर सकते हैं, जिन्हें वे लागू करना चाहिए (यदि हां, तो एक उदाहरण की सराहना की जाएगी)?

समेकित करने के लिए, मुझे इस मामले में क्या उपयोग करना चाहिए, जब मैं यह सुनिश्चित करना चाहता हूं कि उसी प्रकार के सभी वर्गों में विशेष तरीके हों और उन्हें अपने तरीके से लागू करें?

+1

'NotImplementedError' और हवाई जहाज के लैंडिंग गियर के बारे में क्या उद्धरण है? "ओम नामांकन" के लिए –

उत्तर

9

रूबी इस कार्यक्षमता की पेशकश नहीं करता है, नहीं। आप यह सुनिश्चित करने के लिए ज़िम्मेदार हैं कि आपके वर्ग लागू करें जो उन्हें लागू करना चाहिए।

रूबी के लिए ऐसी कार्यक्षमता असंभव है कि रूबी वर्गों को फिर से खोल दिया जा सकता है, और रूबी रनटाइम पर मनमाने ढंग से कोड लोड करने का समर्थन करता है, इसलिए हम नहीं जान सकते कि कक्षा एक निश्चित इंटरफ़ेस लागू करती है जब तक हम कॉल करने का प्रयास नहीं करते यह।

मान लें कि एक Animal एक eat विधि होनी चाहिए, और मैं निम्नलिखित है:

class Cat < Animal 
    def talk 
    puts "meow" 
    end 
end 

class Cat 
    def eat 
    puts "om nom nom" 
    end 
end 

उस फ़ाइल के अंत तक, Cat, अपने eat परिभाषा होगा क्योंकि रूबी कक्षाएं फिर से खोल दी और संशोधित कर सकते हैं कई बार । क्या पहली परिभाषा के बाद कोड त्रुटि होनी चाहिए क्योंकि eat अभी तक परिभाषित नहीं किया गया था? यह कार्यान्वयन इससे मदद मिलेगा इससे ज्यादा नुकसान होगा, क्योंकि वर्गों को फिर से खोलना आम है, भले ही यह उदाहरण दूषित हो। eat विधि को बुलाए जाने के बाद यह त्रुटि होनी चाहिए और अस्तित्व में नहीं है, तो हम निश्चित हो सकते हैं कि इसे परिभाषित करने के बाद इसे परिभाषित किया जाए? खैर, अगर विधि गुम हो गई थी, तो होगा, वैसे भी। दुभाषिया कभी नहीं जानता कि दूसरी कक्षा परिभाषा रास्ते पर है, इसलिए जब तक विधि वास्तव में बुलाया जाता है तब तक यह आपको कभी भी काट नहीं सकता है।

संक्षेप में, सुपरक्लास को संभवतः रूबी में परिभाषित करने की विधि की आवश्यकता नहीं होती है, क्योंकि कक्षाओं की गतिशील प्रकृति इस तरह के एक लक्ष्य का विरोध करती है।

क्षमा करें! यह एक ऐसा स्थान है जहां इकाई परीक्षण आसान हो सकता है, हालांकि, यह सुनिश्चित करने के लिए कि आपके उप-वर्ग ऐसा करते हैं जो वे कर रहे हैं, वैसे भी।

+0

+1: डी क्या आपने [कार्यान्वयन] देखा है (http://www.facebook.com/video/video.php?v=1055625287695)? – edgerunner

+0

मुझे विश्वास है कि यह रूबी में नहीं किया जा सकता है, लेकिन मुझे संदेह है कि संकलन के साथ इसके साथ कुछ लेना देना है। पाइथन में मेटाक्लास "एबीसीएमटा" का उपयोग करके एक आम सार आधार श्रेणी डिजाइन पैटर्न है, और इसके लिए कोई संकलन की आवश्यकता नहीं है। –

+0

@SteveZelaznik: मेला, संपादित :) महत्वपूर्ण बात यह है कि यह रनटाइम पर कक्षा को फिर से खोलने और लोड करने का समर्थन करता है, जो कि * एक व्याख्याित वातावरण में * आसान तरीका है, लेकिन, हाँ, असंभव नहीं है। किसी भी मामले में, पायथन क्लास फिर से खोलने का समर्थन नहीं करता है, इसलिए यह अमूर्त वर्गों को लागू करने के लिए स्वतंत्र है :) – Matchu

1

रूबी में अमूर्त कक्षाओं के बराबर नहीं है। अधिकांशतः ऐसा इसलिए होता है क्योंकि रूबी गतिशील रूप से टाइप की जाती है, जिसका अर्थ है कि अमूर्त वर्गों की अवधारणा वास्तव में लागू नहीं होती है।

2

यो बस खाली विधियों का उपयोग कर सकते हैं, या उन्हें लागू करने के लिए उप-वर्गों को मजबूर करने के लिए त्रुटियां बढ़ा सकते हैं।

class Base 
    def abstract_method 
    end 

    def mandatory_abstract_method 
    raise NotImplementedError.new("You must implement this") 
    end 
end 

नीचे की ओर यह विधि केवल इसे लागू करने पर लागू होगी। रुबी एक गतिशील भाषा है और इसमें कोई संकलन-समय जांच नहीं है।

19

एक मॉड्यूल का उपयोग करें जो लागू किए जाने वाले तरीकों को परिभाषित करता है।

module Animal 
    def eat 
    raise NotImplementedError 
    end 
end 

class Cat 
    include Animal 

    def eat 
    "Om nom nom" 
    end 
end 

class Dog 
    include Animal 
end 

c = Cat.new 
c.eat # => "Om nom nom" 

d = Dog.new 
d.eat # => NotImplementedError 
0

तुम सच में अमूर्त लागू करना चाहते हैं तो आप अमूर्त मणि का उपयोग करें।

sudo gem install abstraction 

उदाहरण का संदर्भ उदाहरण Abstraction gem WIKI से उदाहरण।

class Car 
    abstract 

    def go_forward 
    # ... 
end 
end 

Car.new 
> AbstractClassError: Car is an abstract class and cannot be instantiated 

class Convertible < Car 
    def door_count 
    2 
    end 
end 

class Sedan < Car 
    def door_count 
    4 
    end 
end 

Convertible.new # => #<Convertible:0x8fdf4> 
+0

यह केवल सार वर्ग के तत्कालता को रोकता है। अब यह सुनिश्चित करता है कि ठोस उपखंडों में अमूर्त विधियां लागू की गई हैं। –

संबंधित मुद्दे