ईएस 6 क्लास मल्टीपल इनहेरिटेंस


134

मैं पर इस पर अपना शोध के सबसे किया है BabelJS और पर MDN (जो सभी में कोई जानकारी नहीं है), लेकिन कृपया मुझे बताओ के लिए स्वतंत्र महसूस अगर मैं नहीं किया है सावधान पर्याप्त ES6 युक्ति बारे में अधिक जानकारी के लिए चारों ओर देख में रहा।

मैं सोच रहा हूं कि ES6 उसी तरह से कई वंशानुक्रम का समर्थन करता है जैसे अन्य बतख-टाइप भाषाएं करती हैं। उदाहरण के लिए, क्या मैं कुछ ऐसा कर सकता हूं:

class Example extends ClassOne, ClassTwo {
    constructor() {
    }
}

नई कक्षा में कई वर्गों का विस्तार करने के लिए? यदि हां, तो दुभाषिया ClassOne से ClassOne के तरीकों / गुणों को पसंद करेगा?


4
यह वर्तमान रास्ता विरासत js में काम करता है के साथ वास्तव में संभव नहीं है, निकटतम आप कर सकते हैं एक है mixin
qwertymk

क्या आप किसी प्रकार का संदर्भ प्रदान कर सकते हैं, जिसमें कहा गया है कि नई युक्ति में यह संभव नहीं है, और यदि हां, तो क्या आप इसका उत्तर दे सकते हैं ताकि मैं इसे स्वीकार कर सकूं?
BTC

मैंने पढ़ा है कि नए ES6 कक्षाएं कोई नई कार्यक्षमता नहीं जोड़ते हैं, वे सिर्फ वाक्य रचना चीनी हैं।
ओरिऑल


@ ऑरिओल, वे सिंटेक्स चीनी हैं, लेकिन मैंने सोचा था कि अगर चीनी आंतरिक रूप से कई वर्गों के साथ कुछ कर रही थी।
बीटीसी

जवाबों:


70

एक वस्तु में केवल एक ही प्रोटोटाइप हो सकता है। दो माता-पिता के प्रोटोटाइप के संयोजन के रूप में एक मूल वस्तु बनाकर दो वर्गों से प्रवेश किया जा सकता है।

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


1
मुझे हमेशा आश्चर्य हुआ, क्या __proto__सही वस्तु के लिए प्रॉप लुकअप को फॉरवर्ड करने के लिए लिंक पर एक गटर सेट करने का कोई तरीका है ? मैंने कोशिश की है, लेकिन कभी भी काम करने के लिए इसे प्राप्त नहीं किया है
qwertymk

3
@qwertymk अच्छी तरह से ध्यान में रखते हैं कि __proto__स्वयं एक पदावनत विशेषता है। यह आंतरिक प्रोटोटाइप लिंक को दर्शाता है, लेकिन यह वास्तव में आंतरिक प्रोटोटाइप लिंक नहीं है।
पॉइन्टी

इसलिए कभी भी किसी भी हैक के किसी भी अवसर की तरह कभी काम नहीं करता है? कोर-जेएस ने गेटर्स का उपयोग करके कमजोर समर्थन के साथ कुछ ऐसा ही किया। मल्टीपल इनहेरिटेंस बहुत अच्छा होगा
qwertymk

1
@qwertymk अच्छी तरह से मैं अधिकार के साथ नहीं कह सकता कि क्या यह निश्चित रूप से असंभव है। व्यक्तिगत रूप से मैं जावास्क्रिप्ट में वंशानुक्रम का उपयोग बहुत कम ही करता हूं। वास्तव में मैं प्रोटोटाइप का उपयोग शायद ही कभी उस मामले के लिए करता हूं।
पॉइंटी

2
यहाँ समाधान है जो मैं लेकर आया हूँ: esdiscuss.org/topic/symbol-for-modifying-property-lookup । नमूना: class Foo extends new MultiClass(Bar, Baz, One, Two) { ... }। अंतिम निर्माणकर्ता के तरीकों और गुणों new MultiClassको सर्वोच्च वरीयता देने के लिए पारित किया गया , वे सिर्फ नए प्रोटोटाइप में मिश्रित होते हैं। मुझे लगता है कि अगर ES6 प्रॉक्सी का उपयोग करके फिर से लागू किया जाता है तो एक और बेहतर समाधान मौजूद है, लेकिन अभी तक इसके लिए पर्याप्त देशी समर्थन नहीं है।
त्रुक्त्र

89

नीचे दिए गए मेरे उदाहरण की जांच करें, superउम्मीद के मुताबिक काम करने की विधि। कुछ तरकीबों का उपयोग करके भी instanceof(ज्यादातर समय) काम करता है:

// base class
class A {  
  foo() {
    console.log(`from A -> inside instance of A: ${this instanceof A}`);
  }
}

// B mixin, will need a wrapper over it to be used
const B = (B) => class extends B {
  foo() {
    if (super.foo) super.foo(); // mixins don't know who is super, guard against not having the method
    console.log(`from B -> inside instance of B: ${this instanceof B}`);
  }
};

// C mixin, will need a wrapper over it to be used
const C = (C) => class extends C {
  foo() {
    if (super.foo) super.foo(); // mixins don't know who is super, guard against not having the method
    console.log(`from C -> inside instance of C: ${this instanceof C}`);
  }
};

// D class, extends A, B and C, preserving composition and super method
class D extends C(B(A)) {  
  foo() {
    super.foo();
    console.log(`from D -> inside instance of D: ${this instanceof D}`);
  }
}

// E class, extends A and C
class E extends C(A) {
  foo() {
    super.foo();
    console.log(`from E -> inside instance of E: ${this instanceof E}`);
  }
}

// F class, extends B only
class F extends B(Object) {
  foo() {
    super.foo();
    console.log(`from F -> inside instance of F: ${this instanceof F}`);
  }
}

// G class, C wrap to be used with new decorator, pretty format
class G extends C(Object) {}

const inst1 = new D(),
      inst2 = new E(),
      inst3 = new F(),
      inst4 = new G(),
      inst5 = new (B(Object)); // instance only B, ugly format

console.log(`Test D: extends A, B, C -> outside instance of D: ${inst1 instanceof D}`);
inst1.foo();
console.log('-');
console.log(`Test E: extends A, C -> outside instance of E: ${inst2 instanceof E}`);
inst2.foo();
console.log('-');
console.log(`Test F: extends B -> outside instance of F: ${inst3 instanceof F}`);
inst3.foo();
console.log('-');
console.log(`Test G: wraper to use C alone with "new" decorator, pretty format -> outside instance of G: ${inst4 instanceof G}`);
inst4.foo();
console.log('-');
console.log(`Test B alone, ugly format "new (B(Object))" -> outside instance of B: ${inst5 instanceof B}, this one fails`);
inst5.foo();

छपेगा

टेस्ट डी: ए, बी, सी -> डी के बाहर उदाहरण: सच है
ए से - ए के अंदर उदाहरण: सच
बी से - बी के अंदर उदाहरण: सच
C से -> C के उदाहरण के अंदर: सत्य
डी से -> डी के अंदर उदाहरण: सच
-
टेस्ट ई: ए, सी -> ई के बाहर उदाहरण: सच है
ए से - ए के अंदर उदाहरण: सच
C से -> C के उदाहरण के अंदर: सत्य
ई से - ई के अंदर उदाहरण: सच
-
टेस्ट F: फैली हुई है B -> बाहरी उदाहरण F: true
बी से - बी के अंदर उदाहरण: सच
एफ से - एफ के अंदर उदाहरण: सच
-
टेस्ट जी: रैपर "नया" डेकोरेटर के साथ अकेले उपयोग करने के लिए, सुंदर प्रारूप -> जी के बाहर उदाहरण: सच
C से -> C के उदाहरण के अंदर: सत्य
-
टेस्ट बी अकेले, बदसूरत प्रारूप "नया (बी (ऑब्जेक्ट))" -> बी के बाहर उदाहरण: गलत, यह एक विफल रहता है
बी से - बी के अंदर उदाहरण: सच

चारों ओर बेला की कड़ी


1
आप B का विस्तार करके B (ऑब्जेक्ट) के उस "बदसूरत प्रारूप" को ठीक कर सकते हैं (B||Object)
हारून

@Aaron मुझे यकीन नहीं है कि मैं इस एक पर आपका अनुसरण कर रहा हूं (या आप मेरा अनुसरण कर रहे हैं)। यदि F extends (B||Object)इसके बजाय F extends B(Object), यह बी मिक्सिन का विस्तार करेगा क्योंकि यह (एक फ़ंक्शन के रूप में) तो एफ केवल डिफ़ॉल्ट फ़ंक्शन प्रोटोटाइप का विस्तार करेगा क्योंकि बी को कभी भी निष्पादित नहीं किया गया था। उपयोग करके F extends B(Object)हम वास्तव में बी फंक्शन को अंजाम दे रहे हैं और एफ 'बी' फंक्शन लौटाएगा। इस मामले में यह बी फंक्शन के अंदर परिभाषित बी क्लास है ... क्लास को सही रखने के लिए छोटा हैक।
पोइलिन्का डोरिन

@Aaron हम जो कर सकते हैं वह फंक्शन डिफ़ॉल्ट पैरामेट्स का उपयोग करें const B = (B = Object) => class extends B {और फिर प्रीटियर उपयोग के class F extends B() {लिए उपयोग करें, लेकिन बदसूरत हैक Kappa
Poelinca Dorin

const B = (B) => class extends (B||Object) {आप के inst5 = new (B(Object)); // instance only B, ugly formatसाथ बदलने के लिए inst5 = new (B());, या शायद मैं इस संदर्भ को गलत समझ सकता हूँ ...
हारून

@ ऐरन हाँ जो ठीक काम console.log('from B -> inside instance of B: ${this instanceof B}');करेगा जब तक कि चुड़ैल विफल नहीं होगी Right-hand side of 'instanceof' is not an objectconst B = (B = Object) => class extends B {पहले बताए अनुसार उपयोग करने से इंस्टोफ टेस्ट पास हो जाता है और inst5 = new (B());यदि आप चाहें तो उपयोग के साथ ही आपको प्रदान करता है।
पोइलिन्का डोरिन

23

सर्जियो कार्नेइरो और जॉन के कार्यान्वयन के लिए आपको सभी लेकिन एक वर्ग के लिए एक शुरुआती कार्य को परिभाषित करने की आवश्यकता है। यहां एकत्रीकरण फ़ंक्शन का एक संशोधित संस्करण है, जो इसके बजाय कंस्ट्रक्टरों में डिफ़ॉल्ट मापदंडों का उपयोग करता है। मेरे द्वारा कुछ टिप्पणियाँ भी शामिल हैं।

var aggregation = (baseClass, ...mixins) => {
    class base extends baseClass {
        constructor (...args) {
            super(...args);
            mixins.forEach((mixin) => {
                copyProps(this,(new mixin));
            });
        }
    }
    let copyProps = (target, source) => {  // this function copies all properties and symbols, filtering out some special ones
        Object.getOwnPropertyNames(source)
              .concat(Object.getOwnPropertySymbols(source))
              .forEach((prop) => {
                 if (!prop.match(/^(?:constructor|prototype|arguments|caller|name|bind|call|apply|toString|length)$/))
                    Object.defineProperty(target, prop, Object.getOwnPropertyDescriptor(source, prop));
               })
    }
    mixins.forEach((mixin) => { // outside contructor() to allow aggregation(A,B,C).staticFunction() to be called etc.
        copyProps(base.prototype, mixin.prototype);
        copyProps(base, mixin);
    });
    return base;
}

यहाँ थोड़ा डेमो है:

class Person{
   constructor(n){
      this.name=n;
   }
}
class Male{
   constructor(s='male'){
      this.sex=s;
   }
}
class Child{
   constructor(a=12){
      this.age=a;
   }
   tellAge(){console.log(this.name+' is '+this.age+' years old.');}
}
class Boy extends aggregation(Person,Male,Child){}
var m = new Boy('Mike');
m.tellAge(); // Mike is 12 years old.

यह एकत्रीकरण समारोह एक वर्ग के गुणों और विधियों को पसंद करेगा जो बाद में वर्ग सूची में दिखाई देते हैं।


3
जब मैं प्रतिक्रिया के साथ इसका उपयोग करने की कोशिश करता हूं Component, तो यह काम नहीं करता है। किसी भी अन्य व्यक्ति के लिए सिर्फ FYI करें जो शायद इस उद्देश्य के लिए चाहते थे।
r3wt

यह चर और कार्यों को अधिलेखित करता है जिनका समान नाम है।
विंसेंट होच-डेरी

17

जस्टिन फ़ागनानी ने बहुत ही साफ-सुथरे ( इहो ) तरीके का वर्णन किया है, जिसमें कई वर्गों को एक साथ इस तथ्य का उपयोग करने के लिए कहा गया है कि ES2015 में, कक्षाओं को कक्षा के भावों के साथ बनाया जा सकता है ।

अभिव्यक्तियाँ बनाम घोषणाएँ

असल में, जैसे आप एक अभिव्यक्ति के साथ एक समारोह बना सकते हैं:

function myFunction() {}      // function declaration
var myFunction = function(){} // function expression

आप कक्षाओं के साथ भी ऐसा कर सकते हैं:

class MyClass {}             // class declaration
var MyClass = class {}       // class expression

अभिव्यक्ति का मूल्यांकन रनटाइम पर किया जाता है, जब कोड निष्पादित होता है, जबकि एक घोषणा पहले से निष्पादित होती है।

मिश्रण बनाने के लिए कक्षा के भावों का उपयोग करना

आप इसका उपयोग फ़ंक्शन को बनाने के लिए कर सकते हैं जो गतिशील रूप से केवल तब क्लास बनाता है जब फ़ंक्शन कहा जाता है:

function createClassExtending(superclass) {
  return class AwesomeClass extends superclass {
    // you class body here as usual
  }
}

इसके बारे में अच्छी बात यह है कि आप पूरी कक्षा को पहले से परिभाषित कर सकते हैं और केवल यह तय कर सकते हैं कि किस समय तक आपको फ़ंक्शन को कॉल करना चाहिए।

class A {}
class B {}
var ExtendingA = createClassExtending(A)
var ExtendingB = createClassExtending(B)

यदि आप कई वर्गों को एक साथ मिलाना चाहते हैं, क्योंकि ES6 कक्षाएं केवल एकल वंशानुक्रम का समर्थन करती हैं, तो आपको उन कक्षाओं की एक श्रृंखला बनाने की आवश्यकता होती है, जिनमें उन सभी वर्गों को सम्मिलित करना होता है जिन्हें आप एक साथ मिलाना चाहते हैं। तो मान लें कि आप एक वर्ग C बनाना चाहते हैं जो A और B दोनों का विस्तार करता है, आप ऐसा कर सकते हैं:

class A {}
class B extends A {}
class C extends B {}  // C extends both A and B

इसके साथ समस्या यह है कि यह बहुत स्थिर है। यदि आप बाद में निर्णय लेते हैं कि आप एक वर्ग डी बनाना चाहते हैं जो बी नहीं बल्कि ए का विस्तार करता है, तो आपको एक समस्या है।

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

class Base {} // some base class to keep the arrow functions simple
var A = (superclass) => class A extends superclass
var B = (superclass) => class B extends superclass
var C = B(A(Base))
var D = B(Base)

ध्यान दें कि हम केवल अंतिम क्षण में कैसे तय करते हैं कि कौन सी कक्षाएं पदानुक्रम में शामिल हैं।


8

यह वास्तव में संभव नहीं है जिस तरह से प्रोटोटाइप विरासत में काम करता है। आइए एक नज़र डालते हैं कि विरासत में मिली विरासत कैसे काम करती है

var parent = {a: function() { console.log('ay'); }};
var child = Object.create(parent);
child.a() // first look in child instance, nope let's go to it's prototype
          // then look in parent, found! return the method

आइए देखें कि क्या होता है जब आप एक प्रोप का उपयोग करते हैं जो मौजूद नहीं है:

child.b; // first look in child instance, nope let's go to it's prototype
         // then look in parent, nope let's go to it's prototype
         // then look in Object.prototype, nope let's go to it's prototype
         // then look at null, give up and return undefined

आप उपयोग कर सकते हैं mixins कि कार्यक्षमता के कुछ प्राप्त करने के लिए, लेकिन आप देर से बाध्यकारी नहीं मिलेगा:

var a = {x: '1'};
var b = {y: '2'};
var c = createWithMixin([a, b]);
c.x; // 1
c.y; // 2
b.z = 3;
c.z; // undefined

बनाम

var a = {x: 1}
var o = Object.create(a);
o.x; // 1
a.y = 2;
o.y; // 2

@ पाइंट्टी के उत्तर को स्वीकार करते हुए क्योंकि उन्होंने विस्तार वाले कीवर्ड के बारे में बात की थी, जो कि वास्तविक प्रश्न था, जिसे चारों ओर से फंसाया गया था और इनहेरिटेंस पैटर्न नहीं थे, लेकिन रुचि लेने के लिए धन्यवाद!
बीटीसी

2

मैं इन समाधानों के साथ आता हूं:

'use strict';

const _         = require( 'lodash' );

module.exports  = function( ParentClass ) {

    if( ! ParentClass ) ParentClass = class {};

    class AbstractClass extends ParentClass {
        /**
         * Constructor
        **/
        constructor( configs, ...args ) {
            if ( new.target === AbstractClass )
                throw new TypeError( "Cannot construct Abstract instances directly" );

            super( args );

            if( this.defaults === undefined )
                throw new TypeError( new.target.name + " must contain 'defaults' getter" );

            this.configs = configs;
        }
        /**
         * Getters / Setters
        **/
        // Getting module configs
        get configs() {
            return this._configs;
        }
        // Setting module configs
        set configs( configs ) {
            if( ! this._configs ) this._configs = _.defaultsDeep( configs, this.defaults );
        }
    }

    return AbstractClass;
}

उपयोग:

const EventEmitter  = require( 'events' );
const AbstractClass = require( './abstracts/class' )( EventEmitter );

class MyClass extends AbstractClass {
    get defaults() {
        return {
            works: true,
            minuses: [
                'u can have only 1 class as parent wich was\'t made by u',
                'every othere classes should be your\'s'
            ]
        };
    }
}

जब तक आप अपने चाल-चलन वाली कक्षाओं के साथ इन ट्रिक को बना रहे हैं, तब तक इसे जंजीर बनाया जा सकता है। लेकिन जैसे ही आप कुछ फ़ंक्शन / वर्ग का विस्तार करना चाहते हैं, वैसे ही आपको लूप जारी रखने का कोई मौका नहीं मिलेगा।

const EventEmitter  = require( 'events' );
const A = require( './abstracts/a' )(EventEmitter);
const B = require( './abstracts/b' )(A);
const C = require( './abstracts/b' )(B);

मेरे लिए काम करता है नोड v5.4.1 - धर्म ध्वज के साथ


मुझे नहीं लगता कि आपको नोड 4x और उससे अधिक के लिए सद्भाव ध्वज की आवश्यकता है।
उमैयर

2

पृष्ठ es6-features.org/#ClassInheritanceFromExpressions से , कई वंशानुक्रम की अनुमति देने के लिए एकत्रीकरण फ़ंक्शन लिखना संभव है:

वर्ग आयत एकत्रीकरण (आकार, रंगीन, ZCoord) {} ​​का विस्तार करता है

var aggregation = (baseClass, ...mixins) => {
    let base = class _Combined extends baseClass {
        constructor (...args) {
            super(...args)
            mixins.forEach((mixin) => {
                mixin.prototype.initializer.call(this)
            })
        }
    }
    let copyProps = (target, source) => {
        Object.getOwnPropertyNames(source)
            .concat(Object.getOwnPropertySymbols(source))
            .forEach((prop) => {
            if (prop.match(/^(?:constructor|prototype|arguments|caller|name|bind|call|apply|toString|length)$/))
                return
            Object.defineProperty(target, prop, Object.getOwnPropertyDescriptor(source, prop))
        })
    }
    mixins.forEach((mixin) => {
        copyProps(base.prototype, mixin.prototype)
        copyProps(base, mixin)
    })
    return base
}

लेकिन यह पहले से ही एकत्रीकरण जैसे पुस्तकालयों में प्रदान किया जाता है


1

ES6 मल्टीपल इनहेरिटेंस के लिए मिक्सिन्स का उपयोग करें।

let classTwo = Base => class extends Base{
    // ClassTwo Code
};

class Example extends classTwo(ClassOne) {
    constructor() {
    }
}

3
क्या एकाधिक उत्तराधिकार का मतलब नहीं है one class inherits from 2 or more unrelated classes? आपके उदाहरण से पता चलता है कि एक वर्ग 2 से विरासत में मिला है, लेकिन संबंधित वर्ग। यह एकल वंशानुक्रम है, एकाधिक वंशानुक्रम नहीं है।
vlad-ardelean 19

@ vlad-ardelean वास्तव में संबंध कृत्रिम है, अर्थात। कॉल करके गतिशील रूप से स्थापित किया गया classTwo। वास्तविक श्रेणी की अवधारणा को खो देने से, जेएस के पास वैसे भी कोई संरचनात्मक विरासत नहीं है। ऑफहैंड मैं एक जेएस परिदृश्य की कल्पना नहीं कर सकता, जहां मिक्सिंस अलग-अलग व्यवहार करते हैं जो आप उन्हें वास्तविक ओओ दुनिया से एमआई के रूप में वैचारिक रूप से परिभाषित करने की उम्मीद करेंगे (परिभाषित 'सुपर-चेन के अलावा); हो सकता है कि मुझसे अधिक ज्ञानी कोई व्यक्ति एक आपूर्ति कर सकता है।
कोलापसर

@ कोल्लासर मुझे लगता है कि आप बिल्कुल सही हैं। जेएस में प्रोटोटाइप विरासत है, जिसका अर्थ है एक प्रोटोटाइप श्रृंखला है जहां श्रृंखला के प्रत्येक प्रोटोटाइप में एक एकल माता-पिता होते हैं। जब एक परिभाषित क्रम में प्रोटोटाइप श्रृंखला में कक्षाओं के पूरे समूह में मिश्रण होता है, तो यह प्रभावी रूप से OO दुनिया में MI के समान होता है।
स्टिजन डे विट

1

अच्छी तरह से Object.assign आपको ईएस 6 कक्षाओं के साथ रचना की तरह कुछ और करीब करने की संभावना देता है।

class Animal {
    constructor(){ 
     Object.assign(this, new Shark()) 
     Object.assign(this, new Clock()) 
  }
}

class Shark {
  // only what's in constructor will be on the object, ence the weird this.bite = this.bite.
  constructor(){ this.color = "black"; this.bite = this.bite }
  bite(){ console.log("bite") }
  eat(){ console.log('eat') }
}

class Clock{
  constructor(){ this.tick = this.tick; }
  tick(){ console.log("tick"); }
}

let animal = new Animal();
animal.bite();
console.log(animal.color);
animal.tick();

मैंने इसे कहीं भी इस्तेमाल नहीं किया है, लेकिन यह वास्तव में काफी उपयोगी है। आप उपयोग कर सकते हैंfunction shark(){} कक्षा के बजाय लेकिन इसके बजाय कक्षा का करने के फायदे हैं।

मेरा मानना extendहै कि कीवर्ड के साथ विरासत के साथ अलग चीज केवल यह है कि फ़ंक्शन केवल पर नहीं रहता हैprototype वस्तु पर ही नहीं रहता है।

इस प्रकार अब जब आप करते हैं बनाया गया एक है , विधि, जबकि केवल अपने प्रोटोटाइप एक है विधिnew Shark()sharkbiteeat


यह काम नहीं करेगा। प्रोटोटाइप के तरीकों को मिश्रित नहीं किया जाएगा और बाध्यकारी गलत होगा।
jonschlinkert

1

मल्टीपल क्लास इनहेरिटेंस करने का कोई आसान तरीका नहीं है। मैं इस तरह के व्यवहार को प्राप्त करने के लिए संघ और विरासत के संयोजन का पालन करता हूं।

    class Person {
        constructor(firstname, lastname, age){
            this.firstname = firstname,
            this.lastname = lastname
            this.Age = age
        }

        fullname(){
                return this.firstname +" " + this.lastname;
            } 
    }

    class Organization {
        constructor(orgname){
            this.orgname = orgname;
        }
    }

    class Employee extends Person{
        constructor(firstname, lastname, age,id) {
            super(firstname, lastname, age);
            this.id = id;
        }

    }
    var emp = new Employee("John", "Doe", 33,12345);
    Object.assign(emp, new Organization("Innovate"));
    console.log(emp.id);
    console.log(emp.orgname);
    console.log(emp.fullname());

आशा है कि यह उपयोगी है।


1

इस ES6 समाधान ने मेरे लिए काम किया:

बहु-inheritance.js

export function allOf(BaseClass, ...Mixins) {

  function copyProperties(target, source) {
    const allPropertyNames = Object.getOwnPropertyNames(source).concat(Object.getOwnPropertySymbols(source))

    allPropertyNames.forEach((propertyName) => {
      if (propertyName.match(/^(?:constructor|prototype|arguments|caller|name|bind|call|apply|toString|length)$/))
        return
      Object.defineProperty(target, propertyName, Object.getOwnPropertyDescriptor(source, propertyName))
    })
  }

  class Base extends BaseClass
  {
    constructor (...args) {
      super(...args)

      Mixins.forEach((Mixin) => {
        copyProperties(this, new Mixin(...args))
      })
    }
  }

  Mixins.forEach((mixin) => {
    copyProperties(Base.prototype, Mixin.prototype)
  })

  return Base
}

main.js

import { allOf } from "./multiple-inheritance.js"

class A
{
    constructor(name) {
        this.name = name
    }
    sayA() {
        return this.name
    }
}

class B
{
    constructor(name) {
        this.name = name
    }
    sayB() {
        return this.name
    }
}

class AB extends allOf(A, B)
{
    sayAB() {
        return this.name
    }
}

const ab = new AB("ab")
console.log("ab.sayA() = "+ab.sayA()+", ab.sayB() = "+ab.sayB()+", ab.sayAB() = "+ab.sayAB())

ब्राउज़र-कंसोल पर उपज:

ab.sayA() = ab, ab.sayB() = ab, ab.sayAB() = ab

ES6 है जावास्क्रिप्ट!
बरगी

1

मैंने खुद को जानने का प्रयास करते हुए आधा सप्ताह बिताया, और इस पर एक पूरा लेख लिखा, https://github.com/latitov/OOP_MI_Ct_oPlus_in_JS , और आशा है कि यह आपकी कुछ मदद करता है।

संक्षेप में, यहां बताया गया है कि जावा को जावा में कैसे लागू किया जा सकता है:

    class Car {
        constructor(brand) {
            this.carname = brand;
        }
        show() {
            return 'I have a ' + this.carname;
        }
    }

    class Asset {
        constructor(price) {
            this.price = price;
        }
        show() {
            return 'its estimated price is ' + this.price;
        }
    }

    class Model_i1 {        // extends Car and Asset (just a comment for ourselves)
        //
        constructor(brand, price, usefulness) {
            specialize_with(this, new Car(brand));
            specialize_with(this, new Asset(price));
            this.usefulness = usefulness;
        }
        show() {
            return Car.prototype.show.call(this) + ", " + Asset.prototype.show.call(this) + ", Model_i1";
        }
    }

    mycar = new Model_i1("Ford Mustang", "$100K", 16);
    document.getElementById("demo").innerHTML = mycar.show();

और यहाँ के Expert_with () वन-लाइनर:

function specialize_with(o, S) { for (var prop in S) { o[prop] = S[prop]; } }

फिर से, कृपया https://github.com/latitov/OOP_MI_Ct_oPlus_in_JS देखें


1

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

let Join = (...classList) => {

    class AggregatorClass {

        constructor() {
            classList.forEach((classItem, index) => {

                let propNames = Object.getOwnPropertyNames(classItem.prototype);

                propNames.forEach(name => {
                    if (name !== 'constructor') {
                        AggregatorClass.prototype[name] = classItem.prototype[name];
                    }
                });
            });

            classList.forEach(constructor => {
                Object.assign(AggregatorClass.prototype, new constructor())
            });
        }
    }


    return AggregatorClass

};

1

मेरा जवाब कम कोड की तरह लगता है और यह मेरे लिए काम करता है:

class Nose {
  constructor() {
    this.booger = 'ready'; 
  }

  pick() {
    console.log('pick your nose')
  } 
}

class Ear {
  constructor() {
    this.wax = 'ready'; 
  }

  dig() {
    console.log('dig in your ear')
  } 
}

class Gross extends Classes([Nose,Ear]) {
  constructor() {
    super();
    this.gross = true;
  }
}

function Classes(bases) {
  class Bases {
    constructor() {
      bases.forEach(base => Object.assign(this, new base()));
    }
  }
  bases.forEach(base => {
    base.prototype
    .properties()
    .filter(prop => prop != 'constructor')
    .forEach(prop => Bases.prototype[prop] = base.prototype[prop])
  })
  return Bases;
}


// test it
function dontLook() {
  var grossMan = new Gross();
  grossMan.pick(); // eww
  grossMan.dig();  // yuck!
}

0

es6 के साथ कई विरासत को संभालने के लिए कस्टम फ़ंक्शन के साथ सीमा का उपयोग करें

var aggregation = (baseClass, ...mixins) => {
    let base = class _Combined extends baseClass {
        constructor (...args) {
            super(...args)
            mixins.forEach((mixin) => {
                mixin.prototype.initializer.call(this)
            })
        }
    }
    let copyProps = (target, source) => {
        Object.getOwnPropertyNames(source)
            .concat(Object.getOwnPropertySymbols(source))
            .forEach((prop) => {
            if (prop.match(/^(?:constructor|prototype|arguments|caller|name|bind|call|apply|toString|length)$/))
                return
            Object.defineProperty(target, prop, Object.getOwnPropertyDescriptor(source, prop))
        })
    }
    mixins.forEach((mixin) => {
        copyProps(base.prototype, mixin.prototype)
        copyProps(base, mixin)
    })
    return base
}

class Colored {
    initializer ()     { this._color = "white" }
    get color ()       { return this._color }
    set color (v)      { this._color = v }
}

class ZCoord {
    initializer ()     { this._z = 0 }
    get z ()           { return this._z }
    set z (v)          { this._z = v }
}

class Shape {
    constructor (x, y) { this._x = x; this._y = y }
    get x ()           { return this._x }
    set x (v)          { this._x = v }
    get y ()           { return this._y }
    set y (v)          { this._y = v }
}

class Rectangle extends aggregation(Shape, Colored, ZCoord) {}

var rect = new Rectangle(7, 42)
rect.z     = 1000
rect.color = "red"
console.log(rect.x, rect.y, rect.z, rect.color)


0

मैं अपने समाधान को भी जोड़ दूंगा - इस सूत्र में जो मैंने पढ़ा है, उससे मैंने अपने लिए सबसे अनुकूल पाया।

export const aggregate = (...mixins) => (Base) => {
  const copyProps = (target, source) => {
    Object.getOwnPropertyNames(source)
      .concat(Object.getOwnPropertySymbols(source))
      .forEach((prop) => {
        if (prop.match(/^(?:constructor|prototype|arguments|caller|name|bind|call|apply|toString|length)$/)) {
          return;
        }
        Object.defineProperty(target, prop, Object.getOwnPropertyDescriptor(source, prop));
      });
  };
  mixins.forEach((mixin) => {
    copyProps(Base, mixin);
    copyProps(Base.prototype, mixin.prototype);
  });
  return Base;
};

आप इसे इस तरह उपयोग कर सकते हैं:

class _MyBaseClass {}
const MyBaseClass = aggregate(ExtensionOne, ExtensionTwo)(_MyBaseClass);

0

अवधारणा के प्रमाण के रूप में, मैंने निम्नलिखित कार्य किया। यह कक्षाओं की एक सूची लेता है और उन्हें एक नए वर्ग (अंतिम प्रोटोटाइप जीतता है ताकि कोई संघर्ष न हो) में रचना करता है। एक रचित फ़ंक्शन बनाते समय, उपयोगकर्ता सभी मूल कंस्ट्रक्टरों का उपयोग करना चुन सकता है [ sic! ] या अपने स्वयं के पास। यह इस प्रयोग की सबसे बड़ी चुनौती थी: इस बात का वर्णन करना कि निर्माणकर्ता को क्या करना चाहिए। एक प्रोटोटाइप में तरीकों की नकल करना एक मुद्दा नहीं है, लेकिन नवगठित वस्तु का इरादा तर्क क्या है। या हो सकता है कि यह निर्माणहीन होना चाहिए? पायथन में, मुझे जो पता है, उससे मेल खाता है कंस्ट्रक्टर लेकिन जेएस में फ़ंक्शन अधिक स्वीकार कर रहे हैं, इसलिए कोई एक फ़ंक्शन को बस सब कुछ के बारे में बता सकता है और हस्ताक्षर से यह स्पष्ट नहीं होगा।

मुझे नहीं लगता कि यह अनुकूलित है लेकिन उद्देश्य संभावनाओं की खोज कर रहा था। instanceofउम्मीद के मुताबिक व्यवहार नहीं करेंगे, जो मुझे लगता है कि एक bummer है, क्योंकि क्लास-ओरिएंटेड डेवलपर्स इसे एक टूल के रूप में उपयोग करना पसंद करते हैं।

शायद जावास्क्रिप्ट सिर्फ यह नहीं है।

/*
    (c) Jon Krazov 2019

    Below is an experiment searching boundaries of JavaScript.
    It allows to compute one class out of many classes.

    Usage 1: Without own constructor

    If no constructor is passed then constructor of each class will be called
    with params passed in object. In case of missing params, constructor
    will be called without params.

    Example:

    const MyClass1 = computeClass([Class1, Class2, Class3]);
    const myClass1Instance = new MyClass1({
        'Class1': [1, 2],
        'Class2': ['test'],
        'Class3': [(value) => value],
    });

    Usage 2: With own constructor

    If constructor is passed in options object (second param) then it will
    be called in place of constructors of all classes.

    Example:

    const MyClass2 = computeClass([Class1, Class2, Class3], {
        ownConstructor(param1) {
            this.name = param1;
        }
    });
    const myClass2Instance = new MyClass2('Geoffrey');
*/

// actual function

var computeClass = (classes = [], { ownConstructor = null } = {}) => {
    const noConstructor = (value) => value != 'constructor';

    const ComputedClass = ownConstructor === null
        ? class ComputedClass {
            constructor(args) {
                classes.forEach((Current) => {
                    const params = args[Current.name];

                    if (params) {
                        Object.assign(this, new Current(...params));
                    } else {
                        Object.assign(this, new Current());
                    }
                })
            }
        }
        : class ComputedClass {
            constructor(...args) {
                if (typeof ownConstructor != 'function') {
                    throw Error('ownConstructor has to be a function!');
                }
                ownConstructor.call(this, ...args);
            } 
        };

    const prototype = classes.reduce(
        (composedPrototype, currentClass) => {
            const partialPrototype = Object.getOwnPropertyNames(currentClass.prototype)
                .reduce(
                    (result, propName) =>
                        noConstructor(propName)
                            ? Object.assign(
                                    result,
                                    { [propName]: currentClass.prototype[propName] }
                                )
                            : result,
                    {}
                );

            return Object.assign(composedPrototype, partialPrototype);
        },
        {}
    );

    Object.entries(prototype).forEach(([prop, value]) => {
	Object.defineProperty(ComputedClass.prototype, prop, { value });
    });
    
    return ComputedClass;
}

// demo part

var A = class A {
    constructor(a) {
        this.a = a;
    }
    sayA() { console.log('I am saying A'); }
}

var B = class B {
    constructor(b) {
        this.b = b;
    }
    sayB() { console.log('I am saying B'); }
}

console.log('class A', A);
console.log('class B', B);

var C = computeClass([A, B]);

console.log('Composed class');
console.log('var C = computeClass([A, B]);', C);
console.log('C.prototype', C.prototype);

var c = new C({ A: [2], B: [32] });

console.log('var c = new C({ A: [2], B: [32] })', c);
console.log('c instanceof A', c instanceof A);
console.log('c instanceof B', c instanceof B);

console.log('Now c will say:')
c.sayA();
c.sayB();

console.log('---');

var D = computeClass([A, B], {
    ownConstructor(c) {
        this.c = c;
    }
});

console.log(`var D = computeClass([A, B], {
    ownConstructor(c) {
        this.c = c;
    }
});`);

var d = new D(42);

console.log('var d = new D(42)', d);

console.log('Now d will say:')
d.sayA();
d.sayB();

console.log('---');

var E = computeClass();

console.log('var E = computeClass();', E);

var e = new E();

console.log('var e = new E()', e);

मूल रूप से यहां पोस्ट किया गया है (gist.github.com)।



-3

यहाँ कई वर्गों को विस्तारित करने का एक भयानक / वास्तव में भद्दा तरीका है। मैं एक दो कार्यों का उपयोग कर रहा हूं जो कि बैबेल ने मेरे ट्रांसप्लड कोड में डाल दिए हैं। फ़ंक्शन एक नया वर्ग बनाता है जो class1 को इनहेरिट करता है, और क्लास 1 को class2 विरासत में मिलता है, और इसी तरह। इसके मुद्दे हैं, लेकिन एक मजेदार विचार है।

var _typeof = typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol' ? function (obj) {
  return typeof obj
} : function (obj) {
  return obj && typeof Symbol === 'function' && obj.constructor === Symbol ? 'symbol' : typeof obj
}

function _inherits (subClass, superClass) {
  if (typeof superClass !== 'function' && superClass !== null) {
    throw new TypeError('Super expression must either be null or a function, not ' + (
      typeof superClass === 'undefined' ? 'undefined' : _typeof(superClass)))
  }
  subClass.prototype = Object.create(
    superClass && superClass.prototype,
    {
      constructor: {
        value: subClass,
        enumerable: false,
        writable: true,
        configurable: true
      }
    })
  if (superClass) {
    Object.setPrototypeOf
    ? Object.setPrototypeOf(subClass, superClass)
    : subClass.__proto__ = superClass.__proto__  // eslint-disable-line no-proto
  }
}

function _m (...classes) {
  let NewSuperClass = function () {}
  let c1 = NewSuperClass
  for (let c of classes) {
    _inherits(c1, c)
    c1 = c
  }
  return NewSuperClass
}

import React from 'react'

/**
 * Adds `this.log()` to your component.
 * Log message will be prefixed with the name of the component and the time of the message.
 */
export default class LoggingComponent extends React.Component {
  log (...msgs) {
    if (__DEBUG__) {
      console.log(`[${(new Date()).toLocaleTimeString()}] [${this.constructor.name}]`, ...msgs)
    }
  }
}

export class MyBaseComponent extends _m(LoggingComponent, StupidComponent) {}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.