خصوصیات protected و getter و setter

protected - getter - setter

11 مرداد 1399
خصوصیات protected و getter و setter

خصوصیات protected و getter و setter

در جلسات قبل با مبحث وراثت تا حدی آشنا شدیم و در مورد access modifier ها نیز صحبت کردیم اما هنوز مباحثی باقی مانده است. ما می توانیم کاری کنیم که کلاس های فرزند، متدهای کلاس پدر را overwrite کنند. به طور مثال تصور کنید که من بخواهم درون کلاس Accounting متد addEmployee را بازنویسی کنم:

class AccountingDepartment extends Department {
  constructor(id: string, private reports: string[]) {
    super(id, 'Accounting');
  }

  addEmployee(name: string) {
    if (name === 'Max') {
      return;
    }
    this.employees.push(name);
  }

  addReport(text: string) {
    this.reports.push(text);
  }

  printReports() {
    console.log(this.reports);
  }
}

همانطور که از جلسات قبل به خاطر دارید متد addEmployee در کلاس پدر (یعنی Department) موجود بود و طبق قوانین وراثت ما این متد را در کلاس فرزند نیز خواهیم داشت بنابراین اگر یک متد در کلاس فرزند با همان نام (addEmployee) تعریف کنیم دیگر از متد موجود در کلاس پدر استفاده نخواهیم کرد، بلکه از متد خودمان استفاده می کنیم. به این کار overwrite کردن متد کلاس پدر می گویند. من در متد addEmployee خودم، گفته ام اگر نام وارد شده Max بود هیچ چیزی را return نکن و از متد خارج شو، در غیر این صورت فرد را به لیست کارمندان اضافه کن.

البته با نوشتن کد بالا به خطا برمی‌خوریم و تایپ اسکریپت زیر this.employees خط کشیده و می گوید employees وجود ندارد. چرا؟ اگر یادتان باشد خصوصیت employees که یک آرایه در کلاس پدر بود، از نوع private تعریف شده بود. خصوصیات private شامل قانون وراثت نمی شوند و حتی در کلاس های فرزند قابل دسترسی نیستند. فقط و فقط از طریق خود کلاس قابل دسترسی هستند:

class Department {
  private employees: string[] = [];

راه حل تایپ اسکریپت برای حل این مشکل معرفی یک access modifier دیگر به نام protected است. هر خصوصیت یا متدی که protected باشد، درون خود کلاس یا درون کلاس های فرزند قابل دسترسی است:

class Department {
  protected employees: string[] = [];
// بقیه کد ها //

با انجام این کار دیگر خطایی به ما داده نمی شود.

آشنایی با Getter و Setter ها

getter ها (به معنی «دریافت کننده») و setter ها (به معنی «ثبت کننده») از خصوصیات جالب برنامه نویسی شیء گرا در اکثر زبان های برنامه نویسی هستند. جاوا اسکریپت و تایپ اسکریپت نیز از این قاعده مستثنی نیستند. فرض کنید بخواهیم درون کلاس Accounting خصوصیتی به نام lastReport داشته باشیم و در constructor آن را برابر عضو اول آرایه reports قرار دهیم:

class AccountingDepartment extends Department {
  private lastReport: string;

  constructor(id: string, private reports: string[]) {
    super(id, 'Accounting');
    this.lastReport = reports[0];
  }

  addEmployee(name: string) {
    if (name === 'Max') {
      return;
    }
    this.employees.push(name);
  }

  addReport(text: string) {
    this.reports.push(text);
    this.lastReport = text;
  }

  printReports() {
    console.log(this.reports);
  }
}

در خط اول خصوصیت lastReport را به صورت private تعریف کرده ام، سپس آن را درون constructor مقداردهی کرده ام و نهایتا درون متد addReport آن را برابر text قرار داده ام. حالا فرض کنید بخواهیم به خصوصیت lastReport دسترسی داشته باشیم. این خصوصیت private است بنابراین فقط از درون کلاس به آن دسترسی خواهیم داشت. به نظر شما راه حل چیست؟

در چنین حالاتی که نمی خواهیم private را به چیز دیگری تغییر دهیم، برای دریافت خصوصیات می توانیم از Getter ها استفاده کنیم. برای تعریف یک getter ابتدا کلیدواژه Get را آورده و سپس نامی برای آن انتخاب کنید (دقیقا مثل تعریف یک تابع):

class AccountingDepartment extends Department {
  private lastReport: string;

  get mostRecentReport() {
    if (this.lastReport) {
      return this.lastReport;
    }
    throw new Error('No report found.');
  }
// بقیه کد ها //

همانطور که می بینید من در کلاس بالا یک getter تعریف کرده ام (به نام mostRecentReport) که به من اجازه دسترسی به lastReport را خارج از کلاس می دهد. منطق آن هم بدین شکل است که اگر lastReport تعریف شده بود (undefined نباشد)، خود lastReport را return می کند در غیر این صورت یک خطا پرتاب می کنیم. بنابراین با استفاده از getter می توانیم خارج از کلاس هم به خصوصیات private دسترسی داشته باشیم. حالا نحوه کار آن چگونه است؟

حالا باید با نحوه کار این Getter آشنا شویم. ما اگر در کد های خارج از کلاس خود، قبل از اضافه کردن report (با استفاده از متد addReport) سعی کنیم mostRecentReport را صدا بزنیم با خطا مواجه می شویم:

const accounting = new AccountingDepartment('d2', []);
console.log(accounting.mostRecentReport);

accounting.addReport('Something went wrong...');

توجه داشته باشید که هنگام استفاده از getter ها باید آن ها را به صورت خصوصیت (property) صدا بزنید نه متد، بنابراین هیچ پرانتزی بعد از نامشان نمی آوریم. خروجی کد بالا در کنسول مرورگر به شکل زیر است:

Uncaught Error: No report found.

این همان پیام خطایی است که در منطق getter خود نوشته بودیم تا در صورتی که lastReport برابر undefined بود، این خطا نمایش داده شود. حالا اگر mostRecentReport را بعد از addReport صدا بزنیم خطایی نخواهیم داشت:

const accounting = new AccountingDepartment('d2', []);

accounting.addReport('Something went wrong...');
console.log(accounting.mostRecentReport);

خروجی کد بالا در کنسول مرورگر به شکل زیر خواهد بود:

Something went wrong…

این هم مبحث getter ها و نحوه استفاده از آن ها، اما setter ها چه چیزی هستند؟ getter ها برای خواندن و دریافت اطلاعات بودند و setter ها برای نوشتن و تعیین اطلاعات هستند. به setter زیر توجه کنید:

  set mostRecentReport(value: string) {
    if (!value) {
      throw new Error('Please pass in a valid value!');
    }
    this.addReport(value);
  }

ما به جای get باید از کلیدواژه set استفاده کرده ایم. اگر دقت کنید نام getter و setter ما یکی است اما این مسئله مشکلی به وجود نمی آورد. با این کار می توانیم از mostRecentReport هم برای دریافت اطلاعات و هم برای نوشتن اطلاعات استفاده کنیم. در واقع می توان گفت:

const accounting = new AccountingDepartment('d2', []);

accounting.mostRecentReport = 'Year End Report';
accounting.addReport('Something went wrong...');
console.log(accounting.mostRecentReport);

از آنجا که در کد بالا mostRecentReport را برابر یک مقدار ('Year End Report') قرار داده ایم، از نوع setter حساب می شود و در آخرین خط کد بالا که مقداری به آن نداده ایم getter حساب خواهد شد. توجه داشته باشید که setter ها را نیز به صورت تابع صدا نمی زنیم بلکه مثل یک خصوصیت ساده عمل می کنند. با اجرای کد بالا در کنسول مرورگر شاهد یک آرایه از report ها خواهیم بود:

[“Year End Report”, “Something went wrong…”]

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

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

محمد شریف فیض
09 اردیبهشت 1401
بخش آخر اشتباه است و lastReport یک string است نه یک array

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

سهیل
21 بهمن 1400
سلام ، بخش اخر این اموزش به اشتباه گفتین یک ارایه لاگ میندازه

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

مقالات مرتبط
ما را دنبال کنید
اینستاگرام روکسو تلگرام روکسو ایمیل و خبرنامه روکسو