مهدی عادلی فر
بنیانگذار توسینسو و برنامه نویس

آموزش نکات کار با کلاسها در اکمااسکریپت ES6

در مطلب قبل گفتیم که کلاس ها در ES6 در زبان جاوااسکریپت معرفی شده اند. در این مطلب به صورت کامل نحوه استفاده از کلاس ها و امکانات آنها را توضیح می دهیم.

دوره های شبکه، برنامه نویسی، مجازی سازی، امنیت، نفوذ و ... با برترین های ایران

تعریف کلاس

برای تعریف کلاس از کلمه کلیدی class استفاده می شود و همیشه در داخل بدنه کلاس از متد constructor استفاده می شود. متد constructor هر وقت که یک شی از کلاس ساخته شود فراخوانی می شود. برای مثال در ادامه یک کلاس ساده با نام Car تعریف کرده ایم.

class Car {
  constructor(brand) {
    this.carname = brand;
  }
}

در داخل بدنه متد constructor خصوصیت های کلاس تعریف شده است. برای مثال در کد بالا یک خصوصیت به نام carname تعریف شده است. حال هر وقت که لازم داشتیم می توانیم از این کلاس استفاده کنیم. نحوه استفاده از کلاس به این شکل است که باید از آن یک شی جدید بسازیم. برای ساخت شی جدید از کلاس از کلمه کلیدی new  استفاده می شود. برای مثال در کد زیر یک شی از کلاس Car ساخته شده است  و ورودی متد constructor که یک برند است را نیز برابر Ford قرار داده ایم. در کد بالا کلمه کلیدی this به شیئی اشاره دارد که از کلاس ساخته شده است.

let mycar = new Car("Ford");

متدها(Method)

همانطور که گفتیم کلاس ها یک متد همیشگی به نام contructor دارند. Contructor یک متد خاص است و برای مقداردهی به خصوصیات کلاس به کار می رود. همچنین این متد به صورت اتوماتیک فراخوانی می شود و نام  آن باید حتما constructor باشد. حال علاوه بر این متد شما می توانید هر چند تا متد که لازم داشته باشید را به بدنه کلاس اضافه کنید. نحوه تعریف متد ساده است در کد زیر در داخل کلاس Car یک متد به نام showMessage تعریف شده است.

class Car {
  constructor(brand) {
    this.carname = brand;
  }
  showMessage () {
    return "I have a " + this.carname;
  }
}
let mycar = new Car("Ford");
alert( mycar.showMessage ());

همانطور که در کد بالا دیده می شود نحوه فراخوانی یک متد به این صورت است  که نام شی را نوشته بعد علامت نقطه و بعد از آن نام متد را می نویسیم و بعد از آن پرانتز قرار می گیرد. دقت داشته باشید که اگر متد ما ورودی هم داشته باشد ورودی ها به ترتیب بین پرانتز قرار می گیرند. برای مثال کد بالا را طوری تغییر داده ایم که متد ما ورودی هم داشته باشد.

class Car {
  constructor(brand) {
    this.carname = brand;
  }
  showMessage (x) {
    return x + ", I have a " + this.carname;
  }
}
let mycar = new Car("Ford");
alert( mycar.showMessage ("Hello"));

می بینید که کلمه Hello را به عنوان ورودی به متد showMessage داده ایم.

متدهای استاتیک(Static Method)

متدهای استاتیک یک سری متدها هستند که در داخل خود کلاس تعریف می شوند و نیازی نیست که برای استفاده از آن بخواهیم یک شی تعریف کنیم و می توانیم مستقیم آن را از کلاس فراخوانی کنیم. برای تعریف متد استاتیک از کلمه کلیدی static استفاده می کنیم. برای مثال در کد زیر متد hello یک متد استاتیک است:

class Car {
  constructor(brand) {
    this.carname = brand;
  }
  static hello() {
    return "Hello!!";
  }
}
let mycar = new Car("Ford");
alert( Car.hello());

دقت کنید که در خط آخر نام کلاس را نوشته ایم و نه نام  شی را اگر نام شی را بنویسیم و متد استاتیک را فراخوانی کنیم با خطا مواجه می شویم یعنی alert( mycar.hello()); غلط است.

دقت کنید که متد استاتیک به صورت مستقیم نمی تواند بر روی خصوصیات کلاس دسترسی یا تغییری داشته باشد زیرا که خصوصیات کلاس مربوط به همان شی است و به صورت پویا تغییر می کند ولی متدهای استاتیک ثابت هستند برای این که بخواهیم بر روی خصوصیات یک کلاس در متد استاتیک کار کنیم باید یک شی از آن کلاس را به عنوان ورودی به متد استاتیک بدهیم. مانند کد زیر:

class Car {
  constructor(brand) {
    this.carname = brand;
  }
  static hello(x) {
    return "Hello " + x.carname;
  }
}
let mycar = new Car("Ford");
alert( Car.hello(mycar));

وراثت Inheritance

کلاس ها می توانند خصوصیات و متدهای کلاس دیگر را به ارث ببرند. یعنی ما در یک کلاس یک سری متد داریم. حال کلاسی که از کلاس ما وراثت داشته است هم همان متدها را دارد بدون آن که بخواهد آنها را دوباره تعریف کند. به کلاسی که وراثت از آن انجام شده است کلاس پدر و به کلاس وارث کلاس فرزند گفته می شود. برای تعریف وراثت از کلمه کلیدی extends استفاده می کنیم. در مثال زیر یک کلاس به نام Model داریم که از کلاس Car ارث بری داشته است. به نحوه استفاده از متدهای کلاس Car دقت کنید.

class Car {
  constructor(brand) {
    this.carname = brand;
  }
  showMessage() {
    return 'I have a ' + this.carname;
  }
}
class Model extends Car {
  constructor(brand, mod) {
    super(brand);
    this.model = mod;
  }
  show() {
    return this.showMessage() + ', it is a ' + this.model;
  }
}
mycar = new Model("Ford", "Mustang");
alert( mycar.show());

دقت کنید که متد super به کلاس پدر اشاره می کند و همچنین اگر constructor کلاس پدر دارای ورودی باشد ما باید در کلاس فرزند در داخل constructor با استفاده از متد super متد constructor مربوط به پدر را نیز فراخوانی کنیم و به آن مقدار دهیم.

Getter , Setter

راه استاندارد دسترسی و مقداردهی به خصوصیات یک کلاس این است که آنها را از طریق متد هایی در اختیار کلاس های دیگر قرار دهیم. در این صورت می توانیم بر روی مقداردهی آنها و همچنین استفاده از خصوصیات کنترل داشته باشیم. به همین دلیل از متدهایی به نام getter برای گرفتن مقدار خصوصیت ها و از متدهایی به نام setter برای مقداردهی به خصوصیت ها استفاده می کنیم. برای متدهای getter از کلمه کلیدی get و برای متدهای setter از کلمه کلیدی set استفاده می کنیم. در کد زیر کلاس Car تعریف شده است که برای خصوصیت carname متد getter, setter نوشته شده است.

class Car {
  constructor(brand) {
    this.carname = brand;
  }
  get cnam() {
    return this.carname;
  }
  set cnam(x) {
    this.carname = x;
  }
}
mycar = new Car("Ford");
alert( mycar.cnam);

دقت داشته باشید که در کد بالا در خط آخر ما از پرانتز برای cnam استفاده نکردیم. این امکان وجود دارد که هنگام استفاده از getter می توان پرانتز قرار نداد. دقت داشته باشید که نام getter, setter نمی تواند با نام خصوصیت یکی باشد یعنی ما نمی توانیم در کد بالا نام getter , setter  را carname قرار دهیم. بعضی برنامه نویس ها برای حل این مشکل یک علامت underscore یا زیرخط قبل از نام خصوصیت می گذارند و نام getter, setter را نام خصوصیت قرار می دهند. مانند مثال زیر. دقت داشته باشید که نحوه استفاده از getter,setter بدون پرانتز نیز در کد زیر آمده است.

class Car {
  constructor(brand) {
    this._carname = brand;
  }
  set carname(x) {
    this._carname = x;
  }
  get carname() {
    return this._carname;
  }
}
mycar = new Car("Ford");
mycar.carname = "Volvo";
alert( mycar.carname);

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


مهدی عادلی فر
مهدی عادلی فر

بنیانگذار توسینسو و برنامه نویس

مهدی عادلی، بنیان گذار TOSINSO. کارشناس ارشد نرم افزار کامپیوتر از دانشگاه صنعتی امیرکبیر و #C و جاوا و اندروید کار می کنم. در زمینه های موبایل و وب و ویندوز فعالیت دارم و به طراحی نرم افزار و اصول مهندسی نرم افزار علاقه مندم.

نظرات