ارث بری بین prototype ها

25 آبان 1398
جاوا اسکریپت OOP: ارث بری بین prototype ها

جاوا اسکریپت OOP: ارث بری بین prototype ها

در این جلسه به مفهوم ارث بری (inheritance) می پردازیم. اگر با زبان های برنامه نویسی شیء گرای دیگر کار کرده باشید قطعا می دانید که ارث بری یکی از مفاهیم اساسی شیء گرایی است. مفهوم ارث بری به زبان ساده این است که یک شیء کدهای یک شیء دیگر را به ارث ببرد یا استفاده کند با اینکه این کدها متعلق به خود آن شیء نیست! برای نشان دادن این مفهوم به شما در ابتدا یک شیء Person و سپس یک شیء Customer می سازم که برخی از کدهای Person را به ارث ببرد.

ابتدا یک constructor برای شیء Person:

// Person constructor
function Person(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
}

من برای سادگی بحث فقط نام و نام خانوادگی را برای هر فرد در نظر گرفته ام. حالا یک متد ساده را به Prototype این constructor متصل می کنم:

// Greeting
Person.prototype.greeting = function () {
    return `Hello there ${this.firstName} ${this.lastName}`;
}

Greetings یک متد است که نام و نام خانوادگی فرد را گرفته و به او سلام می کند. در مرحله ی بعد باید کدهایمان را تست کنیم بنابراین یک شیء به نام John از این constructor می سازم و متد greetings آن را console.log می کنم:

const person1 = new Person('John', 'Doe');

console.log(person1.greeting());

خروجی این کد در کنسول مرورگر عبارت Hello there John Doe است. همه چیز طبق انتظار ما پیش می رود و باید وارد مرحله ی بعد شویم. دستور Console.log بالا را کامنت کنید چرا که به آن نیازی نداریم. سپس constructor دیگری برای Customer (خریدار) ایجاد کنید. خصوصیات خریدار ما باید به شکل زیر باشد:

  • نام
  • نام خانوادگی
  • شماره تلفن
  • نوع عضویت (طرح رایگان، اشتراک ویژه و...)

همانطور که می بینید نام و نام خانوادگی افراد بین Person و Customer مشترک است و نیازی به دوباره وارد کردن آن ها نیست بلکه Customer باید این مقادیر را از Person دریافت کند یا به قول خودمان به ارث ببرد. برای ارث بردن کدهای Person باید آن را درون Customer صدا بزنیم:

// Customer constructor
function Customer(firstName, lastName, phone, membership) {
    Person.call(this, firstName, lastName);

}

بگذارید در مورد تابع call به شما توضیح بدهم. حتما می دانید که در زبان جاوا اسکریپت تمام توابع، متد هستند چرا که همه ی توابع در یک شیء قرار دارند. اگر تابعی را درون شیء های تعریف شده ی خودتان قرار ندهید (مثل یک تابع عادی که خارج از اشیاء است) آن تابع درون شیء سراسری جاوا اسکریپت قرار خواهد گرفت که تمام توابع را در خود دارد. بنابراین زمانی که تابعی به صورت عادی تعریف می شود و در شیء سراسری جاوا اسکریپت قرار می گیرد در دسترس همه خواهد بود. به همین خاطر است که هر جایی بخواهیم از آن استفاده می کنم. از طرفی زمانی که تابع ما درون یک شیء مشخص قرار بگیرد، فقط مخصوص آن شیء خواهد بود و دیگران (خارج از آن شیء) به آن دسترسی ندارند. اینجاست که تابع call وارد می شود و به ما اجازه می دهد از توابعی استفاده کنیم که متعلق به اشیاء دیگر است. این تابع به عنوان پارامتر اول خود نام شیء ای را می گیرد که صاحب اصلی کدهای مورد نظر ما است. مثال:

var person = {
    fullName: function () {
        return this.firstName + " " + this.lastName;
    }
}
var person1 = {
    firstName: "John",
    lastName: "Doe"
}
var person2 = {
    firstName: "Mary",
    lastName: "Doe"
}
person.fullName.call(person1);

خروجی این کد عبارت John Doe است. بر این اساس اگر به کد اصلی خود نگاه کنید متوجه خواهید شد که دو خصوصیت firstName و lastName را از Person به ارث برده ایم:

// Customer constructor
function Customer(firstName, lastName, phone, membership) {
    Person.call(this, firstName, lastName);

}

حالا بقیه ی موارد مانند شماره تلفن و نوع عضویت را نیز به صورت جداگانه تکمیل می کنیم:

// Customer constructor
function Customer(firstName, lastName, phone, membership) {
  Person.call(this, firstName, lastName);

  this.phone = phone;
  this.membership = membership;
}

در مرحله ی بعد برای تست این کد باید یک نمونه از customer ایجاد کنیم. مثال:

// Create customer
const customer1 = new Customer('Tom', 'Smith', '555-555-5555', 'Standard');

console.log(customer1);

اگر به مرورگر نگاه کنیم نتیجه را خواهیم دید:

کد های به ارث برده شده در customer
کدهای به ارث برده شده در customer

حالا از شما سوالی دارم: اگر کد زیر را اجرا کنیم چه اتفاقی می افتد؟

console.log(customer1.greeting());

بله با خطا روبرو می شویم! به دلیل اینکه ما هنوز prototype را به ارث نبرده ایم. برای حل این مشکل باید این کار را انجام بدهیم:

// Inherit the Person prototype methods
Customer.prototype = Object.create(Person.prototype);

با این کار یک کپی از prototype مربوط به Person ساخته ایم و آن را به عنوان prototype اشیاء customer قرار داده ایم. حالا می توانیم با خیال راحت کد زیر را اجرا کنیم:

console.log(customer1.greeting());

نتیجه ی این کد عبارت Hello there Tom Smith است و به خوبی کار می کند.

در این مرحله می توانیم greeting را به دلخواه خود override کنیم (برای customer):

// Customer greeting
Customer.prototype.greeting = function () {
    return `Hello there ${this.firstName} ${this.lastName} welcome to our company`;
}

با این کار، متد greeting برای customer تغییر کرده است. برای تست کردن این کد می گوییم:

console.log(customer1.greeting());

خروجی این کد عبارت Hello there Tom Smith welcome to our company می باشد. توجه داشته باشید که متد greeting برای Person هیچ تغییری نمی کند و تغییر بالا فقط در Customer اعمال خواهد شد. همانطور که گفتم درک مبحث prototype در جاوا اسکریپت ممکن است سخت به نظر برسد اما اگر به شکل دقیقی آن را مطالعه کنید هیچ مشکلی نخواهید داشت.

تمام فصل‌های سری ترتیبی که روکسو برای مطالعه‌ی دروس سری شی گرایی در جاوا اسکریپت توصیه می‌کند:
نویسنده شوید
دیدگاه‌های شما (1 دیدگاه)

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

علیرضا
04 شهریور 1400
عالی بود این مبحث واقعا گیجم کرده بود و درکش نمیکردم خیلی خوب توضیح دادین :)

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.