2012-01-02 13 views
57

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

function Stock(/* object with stock names and prices */) { 
    for (var company_name in arguments[0]) { 
     // copy the passed object into the new object created by the constructor 
     this[company_name] = arguments[0][company_name]; 
    } 
} 

// example methods in prototype, their implementation is probably redundant for 
// this question, but list() returns an array with toString() invoked; total() 
// adds up the stock prices and returns them. Using ES5 feature to make 
// inherited properties non-enumerable 

Stock.prototype = { 
    list: function() { 
     var company_list = []; 
     for (var company_name in this) 
      company_list.push(company_name); 
     return company_list.toString(); 
    }, 
    total: function() { 
     var price_total = 0; 
     for (var company_name in this) 
      price_total += this[company_name]; 
     return '$' + price_total; 
    } 
}; 

Object.defineProperties(Stock.prototype, { 
    list: { enumerable: false }, 
    total: { enumerable:false } 
}); 

var portfolio = new Stock({ MSFT: 25.96, YHOO: 16.13, AMZN: 173.10 }); 
portfolio.list(); // MSFT,YHOO,AMZN 
portfolio.total(); // $215.19 

(कोड को छोटा करने के लिए, आप विधि कार्यान्वयन, की तरह बाहर छोड़ सकते हैं: Stock.total = function(){ /* code */ } मैं बस वहाँ में डाल कल्पना होने के लिए)। यदि ओओपी में कई स्थितियों के लिए संरचना का अनुकूलन किया गया है, तो जावास्क्रिप्ट का उपयोग करने वाले अधिकांश लोग प्रोटोटाइप और विरासत का उपयोग कैसे करते हैं? मुझे जावास्क्रिप्ट ऑनलाइन में रचना के बारे में बहुत सारी जानकारी नहीं मिली, केवल अन्य भाषाओं में।

क्या कोई मुझे उपरोक्त कोड का उपयोग करके संयोजन और एकत्रीकरण का प्रदर्शन करने के लिए एक उदाहरण दे सकता है?

+1

प्रश्न बहुत अस्पष्ट है। शायद [programmers.se] के लिए बेहतर फिट (http://programmers.stackexchange.com)। –

+1

यदि यह बहुत अस्पष्ट है, तो आईएमओ यह किसी भी साइट के लिए उपयुक्त नहीं है। –

+3

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

उत्तर

72

रचना बनाम विरासत से निपटने के दौरान भाषा अप्रासंगिक है। यदि आप समझते हैं कि कक्षा क्या है और कक्षा के उदाहरण क्या है, तो आपको अपनी आवश्यकता है।

संरचना तब होती है जब कक्षा अन्य कक्षाओं के बनायी जाती है; या इसे एक और तरीका कहने के लिए, किसी ऑब्जेक्ट का एक उदाहरण अन्य ऑब्जेक्ट्स के उदाहरणों के संदर्भ में है।

विरासत तब होती है जब किसी वर्ग को किसी अन्य वर्ग से विधियों और गुणों को प्राप्त होता है।

मान लें कि आपके पास दो कार्यक्षमता, ए और बी हैं। आप एक तीसरी कार्यक्षमता को परिभाषित करना चाहते हैं, सी, जिसमें ए या बी दोनों के कुछ या सभी हैं, आप या तो बी और ए से सी बढ़ा सकते हैं, इस मामले में सी में सबकुछ बी और ए है क्योंकि सी isA बी और ए, या आप सी के प्रत्येक उदाहरण को ए का एक उदाहरण और बी का उदाहरण दे सकते हैं, और उन कार्यक्षमताओं पर वस्तुओं का आह्वान कर सकते हैं। बाद के मामले में, प्रत्येक उदाहरण सी प्रभाव में बी के एक उदाहरण और ए

बेशक, भाषा के आधार पर, हो सकता है कि आप कक्षा 2 कक्षाओं (जैसे जावा एकाधिक विरासत का समर्थन नहीं करते हैं), लेकिन यह एक भाषा विशिष्ट विवरण है जिसमें अवधारणा से कोई लेना देना नहीं है।

अब, भाषा विशेष जानकारी के लिए ...

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

तो हमारे उदाहरण के साथ जा रहा है ऊपर, आप ए, बी, और सी

विरासत के लिए, आप

// define an object (which can be viewed as a "class") 
function A(){} 

// define some functionality 
A.prototype.someMethod = function(){} 

होता आप सी ए का विस्तार करना चाहता था, तो आप

करना होगा है

अब सी के प्रत्येक उदाहरण विधि someMethod, क्योंकि सी "ईसा" ए के प्रत्येक उदाहरण

जावास्क्रिप्ट (इस पर बाद में अधिक) एकाधिक वंशानुक्रम * नहीं है के लिए होता है, तो आप सी का विस्तार नहीं हो सकता ए और बी दोनों आप कार्यक्षमता का उपयोग कर सकते हैं, हालांकि, इसे कार्यक्षमता देने के लिए।दरअसल, यह कुछ कारणों से रचना को प्राथमिकता के कारणों में से एक है; कार्यक्षमता संयोजन पर कोई सीमा नहीं है (लेकिन यह एकमात्र कारण नहीं है)।

function C(){ 
    this.a = new A(); 
    this.b = new B(); 
} 

// someMethod on C invokes the someMethod on B. 
C.someMethod = function(){ 
    this.a.someMethod() 
} 

तो विरासत और संरचना दोनों के लिए आपके सरल उदाहरण हैं। हालांकि, यह कहानी का अंत नहीं है। मैंने पहले कहा था कि जावास्क्रिप्ट एकाधिक विरासत का समर्थन नहीं करता है, और एक अर्थ में ऐसा नहीं होता है, क्योंकि आप किसी ऑब्जेक्ट के प्रोटोटाइप को एकाधिक ऑब्जेक्ट्स के प्रोटोटाइप से आधार नहीं बना सकते हैं; क्योंकि जैसे ही आप तीसरे, रेखा करते हैं, तो आप सिर्फ दूसरी पंक्ति undid यानी आप

C.prototype = new B(); 
C.prototype.constructor = B; 
C.prototype.constructor = A; 

नहीं कर सकते। इसका instanceof ऑपरेटर के लिए प्रभाव पड़ता है।

बहरहाल, यह वास्तव में, कोई फर्क नहीं पड़ता क्योंकि सिर्फ इसलिए कि आप एक वस्तु के निर्माता दो बार फिर से परिभाषित नहीं कर सकते, आप किसी भी ऐसे तरीकों आप चाहते हैं एक वस्तु के प्रोटोटाइप के लिए जोड़ सकते हैं। तो सिर्फ इसलिए कि आप ऊपर के उदाहरण ऐसा नहीं कर सकते, आप अभी भी कुछ भी जोड़ सकते हैं आप C.prototype को, दोनों ए और बी

कई चौखटे के प्रोटोटाइप पर सभी तरीकों सहित इस समर्थन करते हैं और यह चाहते हैं आसान। मैं बहुत सारे स्प्राउटकोर काम करता हूं; कि ढांचे के साथ आप कर सकते हैं

A = { 
    method1: function(){} 
} 

B = { 
    method2: function(){} 
} 

C = SC.Object.extend(A, B, { 
    method3: function(){} 
} 

यहाँ मैं वस्तु शाब्दिक A और B में कार्यक्षमता में परिभाषित किया गया है, और फिर C करने के लिए दोनों की कार्यक्षमता जोड़ा है, इसलिए सी के प्रत्येक उदाहरण के तरीकों 1, 2, और 3 इस में विशेष मामला, extend विधि (ढांचे द्वारा प्रदान की गई) वस्तुओं के प्रोटोटाइप को स्थापित करने के सभी भारी भारोत्तोलन करता है।

संपादित करें - आपकी टिप्पणियों में, आप एक अच्छा सवाल लाते हैं, अर्थात् "यदि आप संरचना का उपयोग करते हैं, तो आप मुख्य वस्तु के दायरे के मुख्य उद्देश्य के दायरे के खिलाफ मुख्य वस्तु के दायरे को कैसे जोड़ते हैं"।

कई तरीकों से हैं। सबसे पहले तर्क पारित करने के लिए है। तो

C.someMethod = function(){ 
    this.a.someMethod(arg1, arg2...); 
} 

यहां आप स्कॉप्स से गड़बड़ नहीं कर रहे हैं, आप बस तर्कों को पार कर रहे हैं। यह एक सरल और बहुत व्यवहार्य दृष्टिकोण है। एक अन्य तरीका यह जावास्क्रिप्ट, जो मूल रूप से आप एक के दायरे से स्थापित करने के लिए अनुमति देता है की call (या apply) तरीकों का उपयोग करने के लिए किया जाएगा करने के लिए (तर्क this से आ सकता है या में पारित किया जाना है, जो कुछ ...)

समारोह।

C.someMethod = function(){ 
    this.a.someMethod.call(this, arg1, arg2...); 
} 

में थोड़ा और अधिक स्पष्ट होना, निम्नलिखित बराबर

C.someMethod = function(){ 
    var someMethodOnA = this.a.someMethod; 
    someMethodOnA.call(this, arg1, arg2...); 
} 

जावास्क्रिप्ट में है, काम करता है, वस्तु हैं ताकि आप उन्हें चर को असाइन कर सकते।

call मंगलाचरण यहाँ this को someMethodOnA के दायरे, जो सी

+0

'this.b.someMethod' आपके उदाहरण में' इस' के बारे में कुछ भी नहीं जानता है। यह कुल की गणना कैसे करेगा या शेयरों की सूची कैसे करेगा? – katspaugh

+0

katspaugh, सही - मैंने इसे सही किया। वास्तव में इसे चलाने के बिना यह सब बाहर लटका ... – hvgotcodes

+0

katspaugh, बी पर 'कुछ विधि' ए पर 'इस' के बारे में नहीं पता, यह सच है। हालांकि, आप सामान्य तर्क स्वीकार करने के लिए विधि लिख सकते हैं। यदि आप वास्तव में उन्नत होना चाहते हैं, तो आप कॉल का उपयोग कर सकते हैं और आवेदन कर सकते हैं; मैं अपना उत्तर अपडेट करता हूं – hvgotcodes

3

का उदाहरण है स्थापित कर रही है ... किसी ने मुझे एक उदाहरण संरचना और एकत्रीकरण प्रदर्शित करने के लिए ऊपर दिए गए कोड का उपयोग कर दे सकते हैं ?

पहली नज़र में प्रदान किया गया उदाहरण जावास्क्रिप्ट में संरचना का प्रदर्शन करने के लिए सबसे अच्छा विकल्प प्रतीत नहीं होता है। Stock निर्माता समारोह के prototype संपत्ति अभी भी दोनों तरीकों total और list दोनों के लिए के लिए आदर्श जगह किसी भी स्टॉक वस्तु की स्वयं की संपत्तियों का उपयोग करते हैं रहता है।

क्या किया जा सकता कंस्ट्रक्टर्स प्रोटोटाइप से इन तरीकों के कार्यान्वयन decoupling और उन्हें वापस वास्तव में वहाँ प्रदान कर रहा है - कोड पुन: उपयोग की एक अतिरिक्त के रूप में अभी तक - mixins ...

उदाहरण:

var Iterable_listAllKeys = (function() { 

    var 
     Mixin, 

     object_keys = Object.keys, 

     listAllKeys = function() { 
      return object_keys(this).join(", "); 
     } 
    ; 

    Mixin = function() { 
     this.list = listAllKeys; 
    }; 

    return Mixin; 

}()); 


var Iterable_computeTotal = (function (global) { 

    var 
     Mixin, 

     currencyFlag, 

     object_keys = global.Object.keys, 
     parse_float = global.parseFloat, 

     aggregateNumberValue = function (collector, key) { 
      collector.value = (
       collector.value 
       + parse_float(collector.target[key], 10) 
     ); 
      return collector; 
     }, 
     computeTotal = function() { 
      return [ 

       currencyFlag, 
       object_keys(this) 
        .reduce(aggregateNumberValue, {value: 0, target: this}) 
        .value 
        .toFixed(2) 

      ].join(" "); 
     } 
    ; 

    Mixin = function (config) { 
     currencyFlag = (config && config.currencyFlag) || ""; 

     this.total = computeTotal; 
    }; 

    return Mixin; 

}(this)); 


var Stock = (function() { 

    var 
     Stock, 

     object_keys = Object.keys, 

     createKeyValueForTarget = function (collector, key) { 
      collector.target[key] = collector.config[key]; 
      return collector; 
     }, 
     createStock = function (config) { // Factory 
      return (new Stock(config)); 
     }, 
     isStock = function (type) { 
      return (type instanceof Stock); 
     } 
    ; 

    Stock = function (config) { // Constructor 
     var stock = this; 
     object_keys(config).reduce(createKeyValueForTarget, { 

      config: config, 
      target: stock 
     }); 
     return stock; 
    }; 

    /** 
    * composition: 
    * - apply both mixins to the constructor's prototype 
    * - by delegating them explicitly via [call]. 
    */ 
    Iterable_listAllKeys.call(Stock.prototype); 
    Iterable_computeTotal.call(Stock.prototype, {currencyFlag: "$"}); 

    /** 
    * [[Stock]] factory module 
    */ 
    return { 
     isStock : isStock, 
     create : createStock 
    }; 

}()); 


var stock = Stock.create({MSFT: 25.96, YHOO: 16.13, AMZN: 173.10}); 

/** 
* both methods are available due to JavaScript's 
* - prototypal delegation automatism that covers inheritance. 
*/ 
console.log(stock.list()); 
console.log(stock.total()); 

console.log(stock); 
console.dir(stock); 

रचना बनाम विरासत ऑनलाइन के बारे में बहुत सारी जानकारी है, लेकिन मुझे जावास्क्रिप्ट के साथ सभ्य उदाहरण नहीं मिला है। ...

मुझे जावास्क्रिप्ट ऑनलाइन में केवल अन्य भाषाओं में संरचना के बारे में बहुत सारी जानकारी नहीं मिली। ...

हो सकता है कि खोज प्रश्न पर्याप्त विशिष्ट नहीं था लेकिन 2012 में भी "जावास्क्रिप्ट Mixin रचना" एक है कि बुरा नहीं दिशा में मार्ग प्रशस्त किया है चाहिए के लिए खोज।

... रचना OOP में स्थितियों का एक बहुत के लिए इष्ट है, तो कैसे सबसे जावास्क्रिप्ट का उपयोग लोग आते ही उपयोग प्रोटोटाइप और विरासत लगता है?

क्योंकि उनमें से अधिकतर उपयोग करते हैं, उन्हें क्या मिला और/या वे क्या हैं। शायद अधिक ज्ञान होना चाहिए जावास्क्रिप्ट के बारे में प्रतिनिधिमंडल आधारित भाषा के रूप में और इसके साथ क्या हासिल किया जा सकता है।

परिशिष्ट:

इस से संबंधित हैं सूत्र, हाल ही में अद्यतन और उम्मीद है कि मदद कर रहा ...

2

मैं वें स्याही मैं आपको सादे जावास्क्रिप्ट (ES5) का उपयोग करके "ऑब्जेक्ट कंपोज़िशन" फैशन में अपने कोड को फिर से लिखना दिखा सकता हूं। मैं ऑब्जेक्ट इंस्टेंस बनाने के लिए फ़ैक्टरी फ़ंक्शंस का निर्माण का उपयोग करता हूं, इसलिए new कीवर्ड की आवश्यकता नहीं है। इस तरह, मैं शास्त्रीय/छद्म-शास्त्रीय/प्रोटोटाइप विरासत पर ऑब्जेक्ट संवर्धन (संरचना) का पक्ष ले सकता है, इसलिए Object.create फ़ंक्शन नहीं कहा जाता है।

/* 
* Factory function for creating "abstract stock" object. 
*/ 
var AbstractStock = function (options) { 

    /** 
    * Private properties :) 
    * @see http://javascript.crockford.com/private.html 
    */ 
    var companyList = [], 
     priceTotal = 0; 

    for (var companyName in options) { 

    if (options.hasOwnProperty(companyName)) { 
     companyList.push(companyName); 
     priceTotal = priceTotal + options[companyName]; 
    } 
    } 

    return { 
    /** 
    * Privileged methods; methods that use private properties by using closure. ;) 
    * @see http://javascript.crockford.com/private.html 
    */ 
    getCompanyList: function() { 
     return companyList; 
    }, 
    getPriceTotal: function() { 
     return priceTotal; 
    }, 
    /* 
    * Abstract methods 
    */ 
    list: function() { 
     throw new Error('list() method not implemented.'); 
    }, 
    total: function() { 
     throw new Error('total() method not implemented.'); 
    } 
    }; 
}; 

/* 
* Factory function for creating "stock" object. 
* Here, since the stock object is composed from abstract stock 
* object, you can make use of properties/methods exposed by the 
* abstract stock object. 
*/ 
var Stock = compose(AbstractStock, function (options) { 

    return { 
    /* 
    * More concrete methods 
    */ 
    list: function() { 
     console.log(this.getCompanyList().toString()); 
    }, 
    total: function() { 
     console.log('$' + this.getPriceTotal()); 
    } 
    }; 
}); 

// Create an instance of stock object. No `new`! (!) 
var portofolio = Stock({MSFT: 25.96, YHOO: 16.13, AMZN: 173.10}); 
portofolio.list(); // MSFT,YHOO,AMZN 
portofolio.total(); // $215.19 

/* 
* No deep level of prototypal (or whatsoever) inheritance hierarchy; 
* just a flat object inherited directly from the `Object` prototype. 
* "What could be more object-oriented than that?" –Douglas Crockford 
*/ 
console.log(portofolio); 



/* 
* Here is the magic potion: 
* Create a composed factory function for creating a composed object. 
* Factory that creates more abstract object should come first. 
*/ 
function compose(factory0, factoryN) { 
    var factories = arguments; 

    /* 
    * Note that the `options` passed earlier to the composed factory 
    * will be passed to each factory when creating object. 
    */ 
    return function (options) { 

    // Collect objects after creating them from each factory. 
    var objects = [].map.call(factories, function(factory) { 
     return factory(options); 
    }); 

    // ...and then, compose the objects. 
    return Object.assign.apply(this, objects); 
    }; 
}; 

फिडल here:

जिसके परिणामस्वरूप वस्तु एक अच्छा फ्लैट बना वस्तु है।

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