JavaScript Advanced Concepts

إتقان الميراث المتعدد في جافاسكريبت: التركيب والتوكيل

Spread the love

لا تدعم جافا سكريبت الميراث المتعدد بنفس الطريقة التي تدعمها لغات مثل بايثون أو جافا. يتجنب هذا الخيار التصميمي تعقيدات مثل “مشكلة الماس”، حيث تنشأ غموضات الميراث. ومع ذلك، من الممكن تحقيق وظائف مماثلة من خلال تقنيات ذكية مثل التركيب والتوكيل السلوكي. تستكشف هذه المقالة هذه الأساليب، مع تسليط الضوء على نقاط قوتها ونقاط ضعفها.

محتويات

التركيب: دمج الوظائف

يتضمن التركيب إنشاء فئة جديدة تستخدم وظائف الفئات الموجودة دون ميراث منها. هذا يعزز التغليف الأفضل ويتجنب عيوب الميراث المتعدد. نحقق هذا من خلال إنشاء مثيلات من الفئات المطلوبة ودمج طرقها في فئتنا الجديدة.

دعونا نوضح ذلك بمثال عملي. لنفترض أن لدينا فئة Car وفئة Engine:


class Car {
  constructor(model) {
    this.model = model;
  }
  drive() {
    console.log(`${this.model} is driving.`);
  }
}

class Engine {
  start() {
    console.log("Engine started.");
  }
  stop() {
    console.log("Engine stopped.");
  }
}

الآن، دعونا ننشئ فئة SportsCar التي تتضمن كل من Car و Engine:


class SportsCar {
  constructor(model) {
    this.car = new Car(model);
    this.engine = new Engine();
  }
  drive() {
    this.engine.start();
    this.car.drive();
  }
  stop() {
    this.engine.stop();
  }
}

let mySportsCar = new SportsCar("Porsche 911");
mySportsCar.drive(); // Output: Engine started. Porsche 911 is driving.
mySportsCar.stop();  // Output: Engine stopped.

في هذا المثال، لا ترث SportsCar من Car أو Engine، لكنها تجمع وظائفها بشكل فعال. هذا النهج بسيط وسهل الفهم.

التوكيل السلوكي: توجيه الطريقة الديناميكي

يقدم التوكيل السلوكي نهجًا أكثر مرونة. تقوم فئة جديدة بتوكيل استدعاءات الطريقة إلى مثيلات من فئات أخرى، مما يسمح بتغييرات سلوكية ديناميكية بناءً على السياق. هذا مفيد بشكل خاص عندما لا تكون العلاقة بين الفئات ثابتة.

دعونا نسترجع مثال Car و Engine. سننشئ فئة DelegatingCar:


class DelegatingCar {
  constructor(delegates = []) {
    this.delegates = delegates;
  }
  addDelegate(delegate) {
    this.delegates.push(delegate);
  }
  performAction(action, ...args) {
    for (const delegate of this.delegates) {
      if (typeof delegate[action] === 'function') {
        return delegate[action](...args);
      }
    }
    throw new Error(`Action '${action}' not found.`);
  }
}

let myDelegatingCar = new DelegatingCar([new Car("Ferrari"), new Engine()]);
myDelegatingCar.performAction('drive'); //Output: Ferrari is driving.
myDelegatingCar.performAction('start'); //Output: Engine started.

تستخدم DelegatingCar طريقة performAction مركزية لتوجيه الطلبات إلى المندوب المناسب. هذا يسمح بمزيد من التحكم الديناميكي، لكنه يضيف تعقيدًا مقارنة بالتركيب البسيط.

اختيار النهج المناسب

يوفر كل من التركيب والتوكيل السلوكي بدائل قوية للميراث المتعدد في جافا سكريبت. التركيب أبسط بشكل عام وأكثر قابلية للقراءة، مما يجعله مناسبًا لمعظم السيناريوهات. يوفر التوكيل السلوكي مرونة أكبر للسلوك الديناميكي ولكنه يضيف تعقيدًا إضافيًا. يعتمد الخيار الأمثل على المتطلبات المحددة لتطبيقك. أولوية الوضوح والصيانة أمر بالغ الأهمية.

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *