ES6 শ্রেণীর একাধিক উত্তরাধিকার


134

আমি এই বিষয়ে আমার বেশিরভাগ গবেষণা বাবেলজেএস এবং এমডিএন (যা সম্পর্কে কোনও তথ্য নেই) নিয়ে করেছি, তবে দয়া করে নির্দ্বিধায় আমাকে ES6 স্পেস সম্পর্কে আরও তথ্যের সন্ধানে যথেষ্ট সতর্কতা অবলম্বন না করে থাকলে বলতে পারেন।

আমি ভাবছি যে ES6 একই ফ্যাশনে একাধিক উত্তরাধিকারকে সমর্থন করে কিনা অন্য হাঁস-টাইপযুক্ত ভাষার মতো করে। উদাহরণস্বরূপ, আমি কি কিছু করতে পারি:

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

নতুন ক্লাসে একাধিক ক্লাস প্রসারিত করতে? যদি তা হয়, তাহলে দোভাষী কী ক্লাসটো থেকে ক্লাসটওয়ের থেকে পদ্ধতি / বৈশিষ্ট্যগুলি পছন্দ করবেন?


4
এই বর্তমান উপায় উত্তরাধিকার JS কাজ করে দিয়ে সত্যিই সম্ভব না থাকে তবে নিকটস্থ আপনি কি করতে পারেন একটি হল mixin
qwertymk

আপনি কি এমন এক প্রকারের রেফারেন্স সরবরাহ করতে পারেন যা জানিয়েছে যে নতুন অনুমানের ক্ষেত্রে এটি সম্ভব নয়, এবং যদি তা হয় তবে আপনি কি এটি একটি উত্তর দিতে পারেন যাতে আমি তা গ্রহণ করতে পারি?
বিটিসি

আমি পড়েছি নতুন ইএস 6 ক্লাসগুলি কোনও নতুন কার্যকারিতা যুক্ত করে না, তারা কেবল সিনট্যাক্স চিনির মতো।
ওরিওল


অরিওল, তারা সিনট্যাক্স চিনির মতো, তবে আমি ভাবছিলাম যে চিনিটি অভ্যন্তরীণভাবে একাধিক শ্রেণীর সাথে কিছু করছে কিনা।
বিটিসি

উত্তর:


70

কোনও বস্তুর কেবল একটি প্রোটোটাইপ থাকতে পারে। দুটি ক্লাস থেকে উত্তোলন দুটি প্যারেন্ট প্রোটোটাইপের সংমিশ্রণ হিসাবে প্যারেন্ট অবজেক্ট তৈরি করে করা যেতে পারে।

সাবক্লাসিংয়ের বাক্য গঠনটি ঘোষণায় এটি করা সম্ভব করে তোলে, যেহেতু extendsক্লজের ডান দিকের দিকটি কোনও অভিব্যক্তি হতে পারে। সুতরাং, আপনি কোনও ফাংশন লিখতে পারেন যা আপনার পছন্দ অনুযায়ী যে মানদণ্ড অনুসারে প্রোটোটাইপগুলিকে একত্রিত করে এবং ক্লাস ঘোষণায় সেই ফাংশনটিকে কল করতে পারেন।


1
আমি সর্বদা ভাবছিলাম, __proto__প্রোপ লুকুকে সঠিক অবজেক্টে ফরোয়ার্ড করার জন্য লিঙ্কটিতে কোনও গেটার সেট করার কোনও উপায় আছে কি? আমি চেষ্টা করেছি কিন্তু কখনও কাজ করতে
পেলাম না

3
@ কিওয়ারটিমক ভালভাবে মনে রাখবেন যে এটি __proto__নিজেই একটি অবচিত বৈশিষ্ট্য। অভ্যন্তরীণ প্রোটোটাইপ লিংক প্রতিফলিত, কিন্তু এটা না সত্যিই অভ্যন্তরীণ প্রোটোটাইপ লিঙ্ক।
পয়েন্টি

তাই কখনও কাজ করার মতো কোনও হ্যাকের কোনও সম্ভাবনা নেই? কোর-জেএসগুলি গ্রাহকগণকে ব্যবহার করে দুর্বলম্যাপ সমর্থন সহ একই রকম কিছু করেছিল। একাধিক উত্তরাধিকার খুব দুর্দান্ত হবে
qwertymk

1
@ কিওয়ারটিমক ভালভাবে আমি এটি অসম্ভব কিনা তা কর্তৃপক্ষের সাথে বলতে পারি না। ব্যক্তিগতভাবে আমি জাভাস্ক্রিপ্টে উত্তরাধিকার খুব খুব কমই ব্যবহার করি। আসলে আমি প্রোটোটাইপগুলি খুব কমই ব্যবহার করি that
পয়েন্টি

2
সমাধানটি আমি এখানে নিয়ে এসেছি: esdiscuss.org/topic/symbol- for-modifying-property-lookup । নমুনা: class Foo extends new MultiClass(Bar, Baz, One, Two) { ... }। শেষ নির্মাতার পদ্ধতি এবং বৈশিষ্ট্যগুলি new MultiClassসর্বাধিক অগ্রাধিকার পেয়েছে, তারা কেবল নতুন প্রোটোটাইপে মিশ্রিত হয়েছে। আমি মনে করি যদি ES6 প্রক্সি ব্যবহার করে পুনরায় বাস্তবায়ন করা হয় তবে এর থেকে আরও ভাল সমাধান পাওয়া যায় তবে এর পক্ষে এখনও পর্যাপ্ত নেটিভ সমর্থন নেই।
trusktr

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();

প্রিন্ট আউট করবে

টেস্ট ডি: ডি, এ, বি, সি -> বাইরের উদাহরণটি প্রসারিত করে: সত্য
এ -> এ এর ​​অভ্যন্তরীণ উদাহরণ থেকে: সত্য
খ -> বি এর অভ্যন্তরীণ উদাহরণ থেকে: সত্য
সি থেকে -> সি এর ভিতরে উদাহরণ: সত্য true
ডি থেকে> - ডি এর অভ্যন্তরীণ উদাহরণ: সত্য
-
টেস্ট ই: এ এর ​​বাইরে, সি -> প্রসারিত: সত্য instance
এ -> এ এর ​​অভ্যন্তরীণ উদাহরণ থেকে: সত্য
সি থেকে -> সি এর ভিতরে উদাহরণ: সত্য true
E -> E এর অভ্যন্তরীণ উদাহরণ থেকে: সত্য
-
পরীক্ষার F: B -> এফ এর বাইরের উদাহরণটিকে সত্য করে দেয়: সত্য
খ -> বি এর অভ্যন্তরীণ উদাহরণ থেকে: সত্য
এফ -> এফ এর ভিতরে উদাহরণ থেকে: সত্য
-
টেস্ট জি: "নতুন" ডেকরেটার সহ একা সি ব্যবহার করতে মোড়ক, সুন্দর বিন্যাস -> জি এর বাইরের উদাহরণ: সত্য instance
সি থেকে -> সি এর ভিতরে উদাহরণ: সত্য true
-
একাই টেস্ট বি, কুশল বিন্যাস "নতুন (বি (অবজেক্ট))" -> বি এর বাইরের উদাহরণ: মিথ্যা, এটি ব্যর্থ হয়েছে
খ -> বি এর অভ্যন্তরীণ উদাহরণ থেকে: সত্য

চারপাশে মজার লিঙ্ক


1
আপনি বি প্রসারিত করে বি (অবজেক্ট) এর "কুরুচিপূর্ণ বিন্যাস" ঠিক করতে পারেন (B||Object)
অ্যারন

অ্যারন আমি সত্যিই নিশ্চিত নই যে আমি আপনাকে এর আগে অনুসরণ করছি (অথবা আপনি আমাকে অনুসরণ করছেন)। F extends (B||Object)পরিবর্তে যদি F extends B(Object)এটি বি মিশ্রণটিকে প্রসারিত করে এটি এটি (একটি ফাংশন হিসাবে) তাই F কেবলমাত্র ডিফল্ট ফাংশন প্রোটোটাইপটি প্রসারিত করে যেহেতু বি কখনও কার্যকর হয় নি। ব্যবহার করে F extends B(Object)আমরা আসলে বি ফাংশনটি নির্বাহ করছি এবং এফ 'বিছিন্ন' যাই হোক না কেন বি ফাংশনটি প্রসারিত করবে, এক্ষেত্রে এটি বি ফাংশনের ভিতরে বি শ্রেণীর সংজ্ঞা দেওয়া আছে ... শ্রেণির নামকরণকে সঠিক রাখতে ছোট হ্যাক।
পোয়েলিংকা ডরিন

অ্যারন আমরা যা করতে পারতাম তা হল ফাংশন ডিফল্ট প্যারামগুলি ব্যবহার করা const B = (B = Object) => class extends B {এবং তারপরে class F extends B() {একটি প্রাকৃতিক ব্যবহারের জন্য ব্যবহার করা, তবে
কুরুচিপূর্ণ

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এটি ব্যবহার করার চেষ্টা করি , এটি কার্যকর হয় না। এই উদ্দেশ্যে অন্য কেউ চাইলে কেবল এফওয়াইআই।
r3wt

এটি একই নামযুক্ত ভেরিয়েবল এবং ফাংশনগুলিকে ওভাররাইট করে।
ভিনসেন্ট হচ-ড্রেই

17

জাস্টিন ফাগনানী ES2015-এ ক্লাস এক্সপ্রেশন দিয়ে ক্লাস তৈরি করা যায় এই বিষয়টি ব্যবহার করে একাধিক ক্লাস রচনা করার জন্য খুব পরিষ্কার ( imho ) উপায় বর্ণনা করেছেন ।

এক্সপ্রেশন বনাম ঘোষণা

মূলত, আপনি যেমন একটি এক্সপ্রেশন দিয়ে একটি ফাংশন তৈরি করতে পারেন ঠিক তেমন:

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 ক্লাসগুলি কেবল একক উত্তরাধিকারকে সমর্থন করে, আপনার ক্লাসগুলির একটি শৃঙ্খলা তৈরি করা দরকার যাতে আপনি একসাথে মিশতে চান এমন সমস্ত ক্লাস থাকে। সুতরাং আসুন আমরা বলি যে আপনি একটি শ্রেণি সি তৈরি করতে চান যা A এবং B উভয়ই প্রসারিত, আপনি এটি করতে পারেন:

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

এটির সাথে সমস্যাটি হ'ল এটি খুব অচল। আপনি যদি পরে সিদ্ধান্ত নেন যে আপনি একটি ক্লাস ডি বানাতে চান যা বি প্রসারিত হবে তবে A নয়, আপনার সমস্যা আছে।

তবে ক্লাসগুলি এক্সপ্রেশন হতে পারে এই বিষয়টি ব্যবহার করে কিছু স্মার্ট কৌতূহলের সাহায্যে আপনি এ এবং বি তৈরি করে ক্লাস হিসাবে সরাসরি নয়, শ্রেণি কারখানা হিসাবে (ব্রেভিটির জন্য তীর ফাংশন ব্যবহার করে) সমাধান করতে পারেন:

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

আপনি কিছু কার্যকারিতা পেতে আপনি মিক্সিনগুলি ব্যবহার করতে পারেন তবে আপনি দেরীতে আবদ্ধ হবেন না:

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 পৃষ্ঠা থেকে , একাধিক উত্তরাধিকারের অনুমতি দেওয়ার জন্য একটি সংগ্রহ ফাংশনটি লেখা সম্ভব:

শ্রেণীর আয়তক্ষেত্র সমষ্টি প্রসারিত করে (আকার, রঙিন, জেডকর্ড)}}

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

@ ভ্লাদ-আরডিলিয়ান আসলে সম্পর্কটি কৃত্রিম, অর্থাৎ। ডাকে ডায়নামিকভাবে প্রতিষ্ঠিত classTwo। একটি আসল শ্রেণি ধারণা না থাকায়, জেএস-এর কোনও কাঠামোগত উত্তরাধিকার নেই । অফহ্যান্ড আমি কোনও জেএসের পরিস্থিতি কল্পনা করতে পারি না যেখানে মিক্সসগুলি সত্য ওও বিশ্ব থেকে নির্ধারিত 'সুপার'-চেইন বাদে) এমআই হিসাবে তাদের ধারণা হিসাবে তুলনা করতে চান তার চেয়ে আলাদা আচরণ করে; আমার চেয়ে বেশি জ্ঞানী কিছু লোক হয়তো সরবরাহ করতে পারে।
কলস্পার

@ কল্লাপার আমি মনে করি আপনি একদম ঠিক আছেন। জেএসের প্রোটোটাইপিকাল উত্তরাধিকার রয়েছে, যার অর্থ একটি প্রোটোটাইপ চেইন রয়েছে যেখানে চেইনের প্রতিটি প্রোটোটাইপের একক পিতা বা মাতা থাকে। একটি সংজ্ঞায়িত ক্রমে প্রোটোটাইপ শৃঙ্খলে পুরো একগুচ্ছ ক্লাসে মিশ্রিত করার সময়, এটি কার্যকরভাবে ওও বিশ্বের এমআই এর সমান।
স্টিজন ডি উইট

1

ওয়েল অবজেক্ট.সেসাইন আপনাকে ES6 ক্লাসের মতো কিছুটা রচনা মতোই কাছাকাছি কিছু করার সম্ভাবনা দেয়।

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();

এবং এখানে বিশেষায়িত_ও () ওয়ান-লাইনার রয়েছে:

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

এস with সহ একাধিক উত্তরাধিকার পরিচালনা করতে কাস্টম ফাংশন সহ পরিমাণ ব্যবহার করুন

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শ্রেণি-ভিত্তিক বিকাশকারীরা এটিকে একটি সরঞ্জাম হিসাবে ব্যবহার করতে পছন্দ করায় এটি অনুমান অনুসারে আচরণ করবে না যা আমার ধারণা।

সম্ভবত জাভাস্ক্রিপ্ট এটি নেই।

/*
    (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

একাধিক ক্লাস বাড়ানোর এক দুর্দান্ত / সত্যই কৃপণ উপায় Here আমি ব্যাবেল আমার ট্রান্সপলড কোডটিতে কয়েকটি দ্য ফাংশন ব্যবহার করছি। ফাংশনটি একটি নতুন শ্রেণি তৈরি করে যা ক্লাস 1, এবং ক্লাস 1 উত্তরাধিকার সূত্রে ক্লাস 2 ইত্যাদি করে। এটির সমস্যাগুলি রয়েছে তবে একটি মজাদার ধারণা।

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) {}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.