2009-05-31 16 views
8

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

PARENTClass = function (basevar) { do something here; }; 
PARENTClass.prototype = { a: b, c: d}; // prototype is auto gen 

// Inheritance goes here 
CHILDClass = function (childvar) { do something; }; 
CHILDClass.prototype = new PARENTClass(*1); // Actual inheritance to the prototype statement 
// Instance 
CHILDInstance = new CHILDClass(whatever); 

ऊपर मेरी समझ जे एस की विरासत को, किसी भी तरह है: ठीक है, जब तक यह काम करता है, मैं की तरह शास्त्रीय विरासत पैटर्न के साथ पूरा करते हैं। लेकिन एक परिदृश्य मुझे नहीं पता कि कैसे कार्यान्वित किया जाए, यह है कि अगर मैं ऑब्जेक्ट सृजन (यानी, कन्स्ट्रक्टर के भीतर) शुरू करने के लिए कुछ प्रारंभ करना चाहता हूं, और नई वस्तु का तुरंत उपयोग किया जा सकता है .... समस्या पर मेरा चित्रण शायद भी स्पष्ट किया जाना है, तो मेरा पीछा सी # छद्म का उपयोग समझाने के लिए मुझे क्या करना चाहते हैं:

class PARENT { 
    public PARENT (basevar) { ... } 
} 
class CHILD : PARENT { 
    public CHILD (basevar) : PARENT (basevar) // constructor of child, and call parent constructor during construct. 
    { ... } 
} 

किसी कारण के लिए, उन्हें निर्माता में करने के लिए सबसे अच्छा तरीका है डाल लगता है (जैसे init UI तत्व।)। किसी के पास यह विचार है कि मैं इसे कैसे कर सकता हूं।

पीएस: * 1 में, मुझे नहीं पता कि मुझे वहां क्या रखना चाहिए। पीएस 2: उपर्युक्त स्थिति में मुझे पता चला कि jquery.inherit लाइब्रेरी क्या कर सकती है, मुझे आश्चर्य है कि लाइब्रेरी का उपयोग नहीं कर रहा है या नहीं। पीएस 3: या मेरी समझ गलत है। चूंकि जावास्क्रिप्ट ओओपी की नकल करने का इरादा नहीं है (इसलिए मैं इसे हैक कहता हूं), इसे लागू करने के लिए "सही" तर्क क्या है।

+0

चेक इस बाहर: http://stackoverflow.com/questions/7486825/javascript-inheritance/12816953#12816953 –

+0

Object.create उपयोग करें() आधार वर्ग से प्रोटोटाइप वारिस के। इस तरह बेस क्लास में उप-वर्ग में बदल जाते हैं लेकिन दूसरी तरफ नहीं। मेरे ब्लॉग पर अधिक जानकारी: http://ncombo.wordpress.com/2013/07/11/javascript-inheritance-done-right/ – Jon

उत्तर

17

यह हैक ऐसा नहीं है;

..classes मौजूद नहीं हैं, और व्यवहार का पुन: उपयोग (वर्ग आधारित भाषाओं में विरासत के रूप में जाना जाता है) कि सेवा कर मौजूदा वस्तुओं क्लोनिंग की एक प्रक्रिया के माध्यम से किया जाता है: के रूप में के रूप में जहां Wikipedia द्वारा परिभाषित जावास्क्रिप्ट, एक नमूने के भाषा है प्रोटोटाइप के रूप में।

जैसा कि यह कहता है, जावास्क्रिप्ट में कक्षाओं का उपयोग नहीं किया जाता है; आपके द्वारा बनाई गई प्रत्येक वस्तु जावास्क्रिप्ट Object से निकली है; जावास्क्रिप्ट में सभी ऑब्जेक्ट्स में prototype ऑब्जेक्ट है, और ऑब्जेक्ट्स के सभी उदाहरण आप 'ऑब्जेक्ट' विधियों और गुणों को उनके ऑब्जेक्ट के प्रोटोटाइप ऑब्जेक्ट से बनाते हैं। अधिक जानकारी के लिए एमडीसी prototype ऑब्जेक्ट संदर्भ पर नज़र डालें।

इस के रूप में, जब आप लाइन फोन:

CHILDClass.prototype = new PARENTClass(); 

यह CHILDClass वस्तु PARENTClass वस्तु है, जो एक प्रभाव विरासत के विचार के समान बनाता है से अपने प्रोटोटाइप वस्तु के लिए तरीके और गुण जोड़ने के लिए अनुमति देता है कक्षा आधारित भाषाओं में मौजूद है। चूंकि prototype ऑब्जेक्ट उस ऑब्जेक्ट के बनाए गए प्रत्येक इंस्टेंस को प्रभावित करता है, इसलिए यह आपके ऑब्जेक्ट के प्रत्येक उदाहरण में पैरेंट ऑब्जेक्ट के तरीकों और गुणों को मौजूद होने की अनुमति देता है।

यदि आप अपने बच्चे के वर्ग के निर्माता में अपने माता-पिता वर्ग के निर्माता को कॉल करना चाहते हैं, तो आप जावास्क्रिप्ट call फ़ंक्शन का उपयोग करें; यह आपको बाल वर्ग के कन्स्ट्रक्टर के संदर्भ में अभिभावक वर्ग के कन्स्ट्रक्टर को कॉल करने की अनुमति देता है, इसलिए आपके बच्चे वर्ग में नए प्रोटोटाइप गुणों को पैरेंट क्लास में सेट किए जाने के लिए सेट करना।

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

+0

अच्छा और व्यापक उत्तर। जोड़ने के लिए बस एक और चीज .. उदाहरण के लिए, उदाहरण के लिए, माता-पिता के कन्स्ट्रक्टर को कॉल करते समय, कुछ जो परी महंगा हो सकता है (जैसे एक्सएमएल से पढ़ना) या उपयोगकर्ता से अवगत (जैसे कॉलिंग अलर्ट) निष्पादित किया जाएगा। यहां तक ​​कि मैंने * 1 में कुछ भी नहीं रखा है, जो मूल रूप से अभी भी निष्पादित किया जाएगा; जब तक मैं स्पष्ट रूप से अभिभावक में जांच नहीं डालता (उदाहरण के लिए, यदि (arguments.length == 0) वापसी;)। क्या यह इसके लिए एक "उचित" समाधान है? क्षमा करें कि मैं एक शुद्ध सख्त ओओपी पृष्ठभूमि से आया था, मैं अभी भी वास्तव में जेएस उन्मुख प्रोग्रामिंग तर्क के लिए उपयोग नहीं किया जाता है। – xandy

+0

हां, इस तरह मैं यह करूँगा - अगर कोई आपके ऑब्जेक्ट का उदाहरण बनाता है जिसके लिए तर्क की आवश्यकता होती है तो आप वैसे भी उन कार्यों को निष्पादित नहीं करना चाहते हैं। –

10

आप मैन्युअल रूप से इस तरह उपवर्ग निर्माता में माता पिता के निर्माता आह्वान कर सकते हैं:

CHILDClass = function (basevar) { 
    PARENTClass.call(this, basevar); 
    // do something; 
}; 

चाल यहाँ call विधि है, जिसमें आप एक अलग वस्तु के संदर्भ में एक विधि को लागू करने की अनुमति देता है का उपयोग कर रहा है। अधिक जानकारी के लिए the documentation of call देखें।

+0

मैंने इस कार्यक्षमता के लिए पूरी खोज की है। मैंने कभी इसे इतना आसान नहीं देखा है। मेरा सवाल है, क्या यह करने के लिए यह एक "स्वीकार्य" तरीका है? जैसा कि, यह एक हैक माना जाएगा? साथ ही, क्या यह वर्तमान है, जैसा कि '__proto__' की तरह बहिष्कृत नहीं किया गया है? –

1

जावास्क्रिप्ट में विरासत पदानुक्रमों के लिए कोई अंतर्निहित समर्थन नहीं है क्योंकि टाइप एक्सटेंशन को एकत्रीकरण के माध्यम से किया जाना चाहिए, यानी ऑब्जेक्ट को सीधे वांछित कार्यक्षमता जोड़ना या उसके प्रोटोटाइप को जोड़ना अगर संपत्ति को उदाहरणों के बीच साझा किया जाना है।

फिर भी, जेएस शास्त्रीय विरासत सहित ऑब्जेक्ट निर्माण के अन्य रूपों को लागू करने के लिए पर्याप्त शक्तिशाली है।

को देखते हुए एक clone function - अपने exampe इस तरह लागू किया जा सकता है - जो 'सही' प्रोटोटाइप विरासत, और नहीं जावास्क्रिप्ट का bastardization उसके जोड़ने के लिए पर्याप्त है:

function ParentClass(baseVar) { 
    // do stuff 
} 

// don't overwrite the prototype object if you want to keep `constructor` 
// see http://joost.zeekat.nl/constructors-considered-mildly-confusing.html 
ParentClass.prototype.a = 'b'; 
ParentClass.prototype.c = 'd'; 

function ChildClass(childVar) { 
    // call the super constructor 
    ParentClass.call(this, childVar); 
} 

// don't inherit from a ParentClass instance, but the actual prototype 
ChildClass.prototype = clone(ParentClass.prototype); 
ChildClass.prototype.e = 'f'; 

यह भी वर्ग के लिए कुछ वाक्यात्मक चीनी जोड़ना संभव नहीं है आधारित विरासत - मेरा अपना कार्यान्वयन can be found here

ऊपर से एक उदाहरण तो

var ParentClass = Class.extend({ 
    constructor: function(baseVar) { 
     // do stuff 
    }, 
    a: 'b', 
    c: 'd' 
}); 

var ChildClass = ParentClass.extend({ 
    e: 'f' 
}); 
1

मैं एक हल्के जावास्क्रिप्ट OOP आवरण प्रदान करता है कि 'क्लास की तरह' विरासत जहां आधार तरीकों को ओवरराइड या आधार कंस्ट्रक्टर्स या सदस्यों कॉल कर सकते हैं मिल गया है पढ़ा होगा। पर

//Define the 'Cat' class 
function Cat(catType, firstName, lastName) 
{ 
    //Call the 'Animal' constructor. 
    Cat.$baseNew.call(this, firstName, lastName); 

    this.catType = catType; 
} 
//Extend Animal, and Register the 'Cat' type. 
Cat.extend(Animal, { type: 'Cat' }, { 
    hello: function(text) 
    { 
     return "meaoow: " + text; 
    }, 
    getFullName: function() 
    { 
     //Call the base 'Animal' getFullName method. 
     return this.catType + ": " + Cat.$base.getFullName.call(this); 
    } 
}) 

//It has a built-in type system that lets you do stuff like: 

var cat = new Cat("ginger", "kitty", "kat"); 
Cat.getType()      // "Cat" 
cat.getBaseTypesAndSelf()   // ["Cat","Animal","Class"] 
cat.getType()      // "Cat" 
cat.isTypeOf(Animal.getType()) // "True" 

var dynamicCat = Class.createNew("Cat", ["tab","fat","cat"]) 
dynamicCat.getBaseTypesAndSelf() // ["Cat","Animal","Class"] 
dynamicCat.getFullName()   // tab: fat cat 

स्रोत कोड उपलब्ध:

आप इस तरह अपने वर्गों को परिभाषित Class.js

मैं अपने ब्लॉग पोस्ट में अधिक जानकारी के बारे में OOP in javascript

1

बस सोचा था कि मैं कुछ उल्लेख करें शास्त्रीय पैटर्न के साथ आप जिन मुद्दों के लिए जा रहे हैं, उनके साथ:

  1. सुपर क्लास (एसएस) पर संदर्भ युद्ध सभी मामलों पर अनिवार्य रूप से स्थिरता के रूप में उपलब्ध होंगे। उदाहरण के लिए, यदि आपके पास सुपर में var arr = [1,2,3] है, और example_1.arr.push (4) example_2.arr.push (5) इन सभी उदाहरणों में परिवर्तन "देखें" देखेंगे।
  2. तो आप 1. अमान के समाधान के साथ हल करते हैं, जिसे जकास "कन्स्ट्रक्टर स्टीलिंग" कहते हैं, लेकिन अब आप कन्स्ट्रक्टर को दो बार कॉल करते हैं: एक बार आपके प्रोटोटाइप के लिए और एक बार कन्स्ट्रक्टर चोरी के लिए। समाधान - आपके प्रोटोटाइप के लिए हेल्परप्रोटोटाइप जैसे एक सहायक का उपयोग करें (मैंने इस पोस्ट में इसका पूरा कार्यान्वयन दिखाया: inheritPrototype method एफडब्ल्यूआईडब्लू, यह अनिवार्य रूप से जकास की पुस्तक और कुछ क्रॉकफोर्ड अध्ययन के पृष्ठ 181 के संयोजन से आया था।

  3. कोई गोपनीयता (लेकिन फिर, आप और इसे पाने के लिए टिकाऊ वस्तु पैटर्न की तरह कुछ का उपयोग करने की आवश्यकता होगी कि नहीं हो सकता है कि आप क्या चाहते)

  4. वस्तु परिभाषा छोड़ दिया है "झूलते": समाधान - अपने किसी भी प्रोटोटाइप के कार्यों के लिए एक कथन कथन जांचें और फिर प्रोटोटाइप को प्रोटोटाइप के साथ परिभाषित करें।

मैंने इस सब के उदाहरण github पर चल रहे हैं !!!

मेरे लिए वास्तव में दोनों को वास्तव में ग्रोक करने के लिए एक चुनौती है: वस्तु निर्माण और विरासत पर जाकास और क्रॉकफोर्ड पुस्तकें। मुझे कुछ अलग जावास्क्रिप्ट टीडीडी ढांचे को आजमाने की भी आवश्यकता है। इसलिए मैंने टीडीडी फ्रेमवर्क और जावास्क्रिप्ट ऑब्जेक्ट क्रिएशन & विरासत दोनों पर निबंध बनाने का निर्णय लिया। इसमें कोड और जेएसपीसी परीक्षण चल रहा है! यहाँ लिंक है: * My GitHub Open Source Essay/Book

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