2009-08-15 18 views
113

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

मेरा प्रश्न: यदि आप कोड जो बढ़ाया जाना चाहिए/उपयोगी होने के लिए शामिल लिख रहे हैं, तो क्यों आप कभी भी यह एक वर्ग होगा? या एक और तरीका रखो, आप हमेशा इसे मॉड्यूल क्यों नहीं बनाते?

मैं केवल एक कारण है कि आप एक वर्ग चाहते हैं के बारे में सोच सकते हैं, और है कि यदि आप वर्ग का दृष्टांत की जरूरत है। ActiveRecord :: बेस के मामले में, हालांकि, आप इसे तुरंत चालू नहीं करते हैं। तो क्या यह इसके बजाय मॉड्यूल नहीं होना चाहिए?

उत्तर

156

मैं सिर्फ (महान किताब माध्यम से) The Well-Grounded Rubyist में इस विषय के बारे में पढ़ा। लेखक समझा की तुलना में मैं तो मैं उसे उद्धृत करता हूँ होगा की एक बेहतर काम करता है:


कोई भी नियम या सूत्र हमेशा सही डिजाइन का परिणाम है। लेकिन यह ध्यान में विचारों की एक जोड़े रखने के लिए जब आप वर्ग बनाम मॉड्यूल निर्णय लेते उपयोगी होता है:

  • मॉड्यूल उदाहरणों जरूरत नहीं है। यह इस प्रकार संस्थाओं या बातें आम तौर पर सबसे अच्छा हैं कि कक्षाओं में मॉडलिंग की है, और विशेषताओं या संस्थाओं या चीजों के गुणों सबसे अच्छा मॉड्यूल में समाहित हैं। संगत रूप से, जैसा कि खंड 4.1.1 में उल्लेख किया गया है, वर्ग नाम संज्ञाएं हैं, जबकि मॉड्यूल नाम अक्सर विशेषण होते हैं (स्टैक बनाम स्टैक जैसा)।

  • एक वर्ग केवल एक सुपर क्लास हो सकता है, लेकिन यह के रूप में कई मॉड्यूल में मिश्रण कर सकते हैं के रूप में यह चाहता है। आप विरासत का उपयोग कर रहे हैं , एक समझदार सुपर क्लास/उपवर्ग संबंध बनाने के लिए प्राथमिकता देते हैं। पर क्लास के एक और केवल सुपरक्लस रिलेशनशिप का उपयोग न करें, जो कक्षाओं को समाप्त करता है, जो कि विशेषताओं के कई सेटों में से एक हो सकता है। ,

    module Vehicle 
    ... 
    class SelfPropelling 
    ... 
    class Truck < SelfPropelling 
        include Vehicle 
    ... 
    

    बल्कि आप ऐसा करते हैं चाहिए::

एक उदाहरण में इन नियमों संक्षेप, यहाँ आप ऐसा नहीं करना चाहिए क्या है

module SelfPropelling 
... 
class Vehicle 
    include SelfPropelling 
... 
class Truck < Vehicle 
... 

दूसरे संस्करण मॉडल संस्थाओं और गुणों को और अधिक अच्छी तरह से। ट्रक वाहन से निकलता है (जो समझ में आता है), जबकि सेल्फप्रॉपलिंग वाहनों की एक विशेषता है (कम से कम, उन सभी को जिन्हें हम दुनिया के इस मॉडल में देखते हैं) - एक विशेषता जो कि ट्रक के आधार पर ट्रक के वंशज बनती है , या वाहन के विशेष रूप।

+5

मुखर जवाब –

+0

महान जवाब +1 –

+0

उदाहरण के लिए +1 यह बड़े करीने से पता चलता - ट्रक एक वाहन है - कोई ट्रक है कि एक वाहन नहीं होगा नहीं है। –

-1

अभी, मैं template डिजाइन पैटर्न के बारे में सोच रहा हूँ। यह सिर्फ एक मॉड्यूल के साथ सही महसूस नहीं करेगा।

9

मेरा लेना: मॉड्यूल व्यवहार साझा करने के लिए हैं, जबकि कक्षाएं वस्तुओं के बीच संबंधों को मॉडलिंग के लिए हैं। आप तकनीकी रूप से सबकुछ ऑब्जेक्ट का एक उदाहरण बना सकते हैं और जो भी मॉड्यूल आप व्यवहार के वांछित सेट प्राप्त करना चाहते हैं, में मिश्रण करते हैं, लेकिन यह एक खराब, खतरनाक और अपठनीय डिजाइन होगा।

+0

यह प्रश्न सीधे तरीके से उत्तर देता है: विरासत एक विशिष्ट संगठनात्मक संरचना को लागू करती है जो आपकी परियोजना को बना सकती है अधिक पठनीय। – emery

9

आपके प्रश्न का उत्तर काफी हद तक प्रासंगिक है। पब के अवलोकन को भरना, पसंद मुख्य रूप से विचाराधीन डोमेन द्वारा संचालित होता है।

और हां, ActiveRecord को उप-वर्ग द्वारा विस्तारित करने के बजाय शामिल किया जाना चाहिए था। एक और ओआरएम - datamapper - ठीक उसी तरह प्राप्त करता है!

4

मुझे एंडी गास्केल का जवाब बहुत पसंद है - बस उस हां को जोड़ना चाहता था, ActiveRecord को विरासत का उपयोग नहीं करना चाहिए, बल्कि एक मॉडल/कक्षा में व्यवहार (अधिकतर दृढ़ता) जोड़ने के लिए एक मॉड्यूल शामिल करना चाहिए। ActiveRecord बस गलत प्रतिमान का उपयोग कर रहा है।

इसी कारण से, मुझे मोंगोएड पर मोंगोएड की तरह बहुत पसंद है, क्योंकि यह डेवलपर को समस्या डोमेन में सार्थक कुछ मॉडलिंग के तरीके के रूप में विरासत का उपयोग करने का मौका देता है।

यह दुख की बात है कि रेल समुदाय में काफी कोई भी नहीं "रूबी विरासत" जिस तरह से यह प्रयोग किया जा चाहिए था का उपयोग कर रहा है - वर्ग पदानुक्रम परिभाषित करने के लिए, बस नहीं व्यवहार जोड़ने के लिए।

38

मुझे लगता है कि मिश्रित एक अच्छा विचार है, लेकिन यहां एक और समस्या है कि किसी ने भी उल्लेख नहीं किया है: नामस्थान टकराव। विचार करें:

module A 
    HELLO = "hi" 
    def sayhi 
    puts HELLO 
    end 
end 

module B 
    HELLO = "you stink" 
    def sayhi 
    puts HELLO 
    end 
end 

class C 
    include A 
    include B 
end 

c = C.new 
c.sayhi 

कौन सा जीतता है? रुबी में, यह बाद वाला हो जाता है, module B, क्योंकि आपने इसे module A के बाद शामिल किया था। अब, इस समस्या से बचना आसान है: सुनिश्चित करें कि module A और module B के स्थिरांक और विधियां संभावित नामस्थानों में हैं। समस्या यह है कि संकलक जब टकराव होता है तो आपको बिल्कुल चेतावनी नहीं देता है।

मुझे तर्क है कि यह व्यवहार प्रोग्रामर की बड़ी टीमों के लिए स्केल नहीं करता है - आपको यह नहीं मानना ​​चाहिए कि class C लागू करने वाले व्यक्ति को प्रत्येक नाम के बारे में पता है। रुबी आपको विभिन्न प्रकार की स्थिर या विधि को ओवरराइड करने देगी। मुझे यकीन नहीं है कि कभी भी सही व्यवहार माना जा सकता है।

+4

यह व्यवहार अधिकांश वातावरण में स्वीकार्य नहीं है –

+2

यह सावधानी का एक बुद्धिमान शब्द है। सी ++ में एकाधिक विरासत नुकसान की याद ताजा करती है। –

+1

क्या इसके लिए कोई अच्छा शमन है? ऐसा लगता है कि क्यों पाइथन एकाधिक विरासत एक बेहतर समाधान है (एक भाषा पी * एससिंग मैच शुरू करने की कोशिश नहीं कर रहा है, बस इस विशिष्ट सुविधा की तुलना करें)। – Marcin