کار با access modifier ها

Working with Access Modifiers

10 مرداد 1399

کلاسی که در جلسه قبل ساختیم (Department) یک کلاس بسیار ساده بود و در برنامه های واقعی داده های بیشتری خواهیم داشت. مثلا فرض کنید یک خصوصیت دیگر به نام employees (به معنی «کارمندان») داشته باشیم:

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

    constructor(n: string) {
        this.name = n;
    }

    describe(this: Department) {
        console.log('Department: ' + this.name);
    }
}

همانطور که می بینید تایپ این خصوصیت را روی یک آرایه رشته ای تنظیم کرده ام. حالا می توانیم یک متد دیگر نیز اضافه کنیم که کارمندان جدیدی به این آرایه اضافه کند:

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

    constructor(n: string) {
        this.name = n;
    }

    describe(this: Department) {
        console.log('Department: ' + this.name);
    }

    addEmployee(employee: string) {
        this.employees.push(employee);
    }
}

این متد یک employee (کارمند) را دریافت کرده و وارد آرایه employees می کند. من یک متد دیگر به نام printEmployeeInformation نیز تعریف می کنم که مسئول چاپ کردن اطلاعات کارمندان ما است:

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

    constructor(n: string) {
        this.name = n;
    }

    describe(this: Department) {
        console.log('Department: ' + this.name);
    }

    addEmployee(employee: string) {
        this.employees.push(employee);
    }

    printEmployeeInformation() {
        console.log(this.employees.length);
        console.log(this.employees);
    }
}

حالا خارج از کلاس، از متدهایی که بالاتر نوشتیم استفاده می کنیم:

const accounting = new Department('Accounting');

accounting.addEmployee('Max');
accounting.addEmployee('Manu');

accounting.describe();
accounting.printEmployeeInformation();

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

2

[“Max”, “Manu”]

یعنی 2 نفر در شرکت ما کارمند هستند که نام هایشان Max و Manu است. تا اینجای کار همه چیز دقیقا طبق خواسته ما پیش رفته است اما کد ما از نظر امنیتی مشکل دارد. ما نه تنها از طریق addEmployee بلکه از طریق دسترسی مستقیم به آرایه employees نیز می توانیم مقدار آن را تغییر دهیم. مثلا به کد زیر نگاه کنید:

accounting.addEmployee('Max');
accounting.addEmployee('Manu');

accounting.employees[2] = 'Anna';

به سادگی توانستیم Anna را به عنوان عضو سوم آرایه اضافه کنیم! در پروژه های بزرگ نباید چنین روشی ممکن باشد چرا که اگر برای یک کار چند روش مختلف داشته باشیم، اعضای تیم برنامه نویسی نمی توانند با هم هماهنگ شوند و کد ما بی نظم و شلوغ می شود. برای حل این مشکل تایپ اسکریپت access modifier ها را معرفی می کند! ما می توانیم خصوصیت employees را روی private تنظیم کنیم یعنی این خصوصیت عمومی نیست و فقط بر اساس متدهای خاصی که خودمان تعیین کنیم قابل دسترسی خواهد بود:

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

این کار را می توانید برای متدها نیز انجام بدهید. زمانی که خصوصیت یا متدی را private یا خصوصی تعریف کنیم یعنی فقط و فقط از درون خود کلاس قابل دسترسی می باشند نه خارج از آن. بنابراین در چنین حالتی برای کد زیر خطا دریافت می کنیم:

accounting.employees[2] = 'Anna';

علاوه بر private یک access modifier دیگر به نام public نیز داریم اما از آنجایی که حالت پیش فرض همیشه public است هیچ گاه نیاز به نوشتن آن نخواهید داشت. باید توجه داشته باشید که جاوا اسکریپت با مفاهیم private و public آشنا نیست (به غیر نسخه های آزمایشی بسیار جدید که فعلا استفاده نمی شوند) بنابراین استفاده از این access modifier ها در تایپ اسکریپت برای نوشتن کدهای بهتر است و در هر صورت در زمانی که کد در مرورگر اجرا شود چنین مفاهیمی را متوجه نمی شود.

من می خواهم name را هم private کنم تا مشکل جدیدی را به شما نشان بدهم:

class Department {
    private name: string;
    private employees: string[] = [];
  
    constructor(n: string) {
      this.name = n;
    }
// بقیه کدها

 اگر به name دقت کرده باشید متوجه می شوید که ما ابتدا این خصوصیت را تعریف کرده ایم و سپس در constructor برایش مقدار تعیین می کنیم. در بسیاری از پروژه های واقعی ما خصوصیات زیادی داریم و اگر بخواهیم به روش بالا عمل کنیم کارمان کمی طاقت فرسا می شود تا جایی که ممکن است constructor ما ده پارامتر ورودی بگیرد. روش خلاصه تری برای تعریف خصوصیات و مقدار دهی به آن ها وجود دارد که به شکل زیر است:

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

  constructor(private id: string, public name: string) {

  }

  describe(this: Department) {
    console.log(`Department (${this.id}): ${this.name}`);
  }
// بقیه کدها //

همانطور که می بینید تعریف خصوصیات را از ابتدای کلاس و مقدار دهی شان را از داخل constructor حذف کرده ام و به جای آن، خصوصیات را به صورت پارامتر برای Constructor آورده ام. توجه کنید که اگر access modifier ها را قبل از نام خصوصیات نیاورید این روش اصلا کار نمی کند و باید دقیقا از حالت بالا پیروی کنید. همچنین باید حواستان باشد که بر حسب عادت آن ها را درون constructor مقدار دهی نکنید، یادتان باشد که این روش یک روش خلاصه شده است و مشکلی ندارد.

حتما متوجه شده اید که متد describe را نیز تغییر داده ام تا خصوصیت id را که جدیدا تعریف کرده ام در قسمت کنسول مرورگر چاپ کند. حالا می توانیم یک نمونه جدید از این کلاس بسازیم:

const accounting = new Department('d1', 'Accounting');
accounting.describe();

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

Department (d1): Accounting

بنابراین کدهایمان بدون مشکل اجرا می شوند.

در نهایت باید با یکی دیگر از access modifier ها به نام readonly آشنا شوید. خصوصیات readonly خصوصیاتی هستند که نباید به هیچ عنوان بعد از مقداردهی اولیه توسط constructor تغییر کنند. به طور مثال در کد بالا id را داشتیم و قطعا کد مربوط به یک دپارتمان خاص تغییر نمی کند بنابراین این خصوصیت از نوع readonly است بنابراین می گوییم:

  constructor(private readonly id: string, public name: string) {

  }

حالا از این به بعد اجازه ویرایش id را نداریم، حتی از درون کلاس! مثلا اگر متد addEmployee را به شکل زیر ویرایش کنم با خطا روبرو می شوم:

  addEmployee(employee: string) {
    this.id = 'd2';
    this.employees.push(employee);
  }

تایپ اسکریپت سریعا زیر id خط می کشد و به من می گوید که id از نوع readonly است و شما اجازه ویرایش یا مقدار دهی دوباره به آن را ندارید. در قست بعد وارد مبحث وراثت می شویم.

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

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

Kourosh
10 مهر 1402
حااجی دمتون گرممم

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

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