13. کلاسها

در اینجا کلاسهای ECMAScript 6 را معرفی میکنیم. ابتدا نشان میدهیم که توابع را میتوان از قبل بهعنوان کلاس استفاده کرد.
13.1. اسکریپت [class-00]
اسکریپت زیر کاربرد غیرمعمولی توابع را نشان میدهد. در اینجا، از آنها بهعنوان اشیاء استفاده میشود.
''use strict';
//یک تابع میتواند بهعنوان یک شیء استفاده شود
// یک پوستهٔ خالی
function f() {
}
// که ویژگیها از خارج به آن اختصاص داده میشوند
f.prop1 = "val1";
f.show = function () {
console.log(this.prop1);
}
// استفاده از f
f.show();
// تابعی g که بهعنوان یک کلاس عمل میکند
function g() {
this.prop2 = "val2";
this.show = function () {
console.log(this.prop2);
}
}
// نمونه سازی تابع با [new]
new g().show();
توضیحات
- خطوط ۵–۷: بدنه تابع f هیچ خصوصیتی را تعریف نمیکند؛
- خطوط ۹–۱۲: ویژگیها از خارج به تابع f اختصاص داده میشوند؛
- خط ۱۴: استفاده از تابع (شیء) f. توجه کنید که ما [f()] را نمینویسیم، بلکه به سادگی [f] را مینویسیم. این نشانهگذاری برای یک شیء است؛
- خطوط ۱۷–۲۲: تابع [g] طوری تعریف شده است که گویی یک کلاس با خواص و متدها است؛
- خط ۲۴: تابع [g] توسط [new g()] نمونه سازی میشود؛
نتایج اجرا
[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\classes\class-00.js"
val1
val2
ES6 مفهوم کلاس را معرفی کرده است، که اکنون به ما امکان میدهد از استفاده از توابع برای ایجاد کلاسها اجتناب کنیم.
13.2. اسکریپت [class-01]
اسکریپت [class-01] کلاس [Personne] را معرفی میکند:
//کلاس
class Personne {
// سازنده
constructor(nom, prénom, âge) {
this.nom = nom;
this.prénom = prénom;
this.âge = âge;
}
// گیرندهها و تنظیمکنندهها
get nom() {
return this._nom;
}
set nom(value) {
this._nom = value;
}
get prénom() {
return this._prénom;
}
set prénom(value) {
this._prénom = value;
}
get âge() {
return this._âge;
}
set âge(value) {
this._âge = value;
}
//از toString به JSON
toString() {
return JSON.stringify(this);
}
}
// فراخوانی کلاس
function main() {
const personne = new Personne("Poirot", "Hercule", 66);
console.log("personne=", personne.toString(), typeof (personne), personne instanceof (Personne));
}
// فراخوانی `main`
main();
توضیحات
- خط ۲: کلمه کلیدی [class] نشاندهنده یک کلاس است؛
- خطوط ۵–۹: کلمه کلیدی [constructor] نشاندهنده سازنده کلاس است. حداکثر یک سازنده وجود دارد. از آن برای ساخت و مقداردهی اولیه یک نمونه از کلاس استفاده میشود. توجه داشته باشید که هیچ اعلانی برای ویژگیهای [nom, prénom, âge] وجود ندارد؛
- خطوط ۱۱–۳۶: ویژگیهای کلاس. اینها شامل عناصری هستند که قبلاً در بخش اشیاء ۴، صفحه ۴۴ پوشش داده شدهاند. تنها نحو آن متفاوت است؛
- خط ۴۱: ایجاد یک شیء از نوع [Personne]. از این پس، شیء [personne] بهعنوان یک شیء صریح (literal object) استفاده میشود. [typeof (personne)] با 'object' برابر است و عبارت [personne instanceof (Personne)] درست است. بنابراین میتوان نوع دقیق یک نمونه کلاس را مشخص کرد؛
نتایج اجرا
[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\classes\class-01.js"
personne= {"_nom":"Poirot","_prénom":"Hercule","_âge":66} object true
13.3. اسکریپت [class-02]
این اسکریپت قابلیت ارثبری از یک کلاس را با استفاده از کلمه کلیدی [extends] نشان میدهد.
ابتدا، کلاس [Personne] را در یک ماژول [Personne.js] ایزوله میکنیم:
// کلاس
class Personne {
// سازنده
constructor(nom, prénom, âge) {
this.nom = nom;
this.prénom = prénom;
this.âge = âge;
}
// گیرندهها و تنظیمکنندهها
get nom() {
return this._nom;
}
set nom(value) {
this._nom = value;
}
get prénom() {
return this._prénom;
}
set prénom(value) {
this._prénom = value;
}
get âge() {
return this._âge;
}
set âge(value) {
this._âge = value;
}
//toString به JSON
toString() {
return JSON.stringify(this);
}
}
//کلاس خروجی
export default Personne;
- خط ۳۹: ما کلاس [Personne] را صادر میکنیم تا اسکریپتها بتوانند آن را وارد کنند؛
اسکریپت [class-02] کلاسی به نام [Enseignant] ایجاد میکند که از کلاس [Personne] مشتق شده است:
// وارداتها
import Personne from './Personne';
// کلاس
class Enseignant extends Personne {
// سازنده
constructor(nom, prénom, âge, discipline) {
super(nom, prénom, âge);
this.discipline = discipline;
}
// گیرندهها و تنظیمکنندهها
get discipline() {
return this._discipline;
}
set discipline(value) {
this._discipline = value;
}
}
// فراخوانی کلاس
function main() {
const enseignant = new Enseignant("Poirot", "Hercule", 66, "détective");
console.log("enseignant=", enseignant.toString(), typeof (enseignant), enseignant instanceof Enseignant);
}
//فراخوانی main
main();
توضیحات
- خط ۲: کلاس [Personne] از ماژول [Personne.js] وارد میشود، که در همان پوشهای قرار دارد که [class-02] در آن قرار دارد؛
- خط ۵: کلاس [Enseignant] با استفاده از کلمه کلیدی [extends] از کلاس [Personne] ارث میبرد: یک ویژگی [_discipline] را به آن اضافه میکند، به همراه گترها و سترهای متناظر؛
- خطوط ۸–۱۱: سازنده کلاس [Enseignant] چهار مقدار را برای مقداردهی اولیه چهار ویژگی کلاس دریافت میکند؛
- خط ۹: کلمه کلیدی [super] کانتراکتور کلاس والد [Personne] را فراخوانی میکند، که در نتیجه ویژگیهای [_nom, _prénom, _âge] را مقداردهی اولیه میکند؛
- خط ۱۰: ویژگی [_discipline] که متعلق به کلاس [Enseignant] است، مقداردهی اولیه میشود؛
- خطوط ۱۴–۱۹: گتر و ستر برای ویژگی [_discipline]؛
- خط ۲۵: یک شیء از نوع [Enseignant] ایجاد میشود؛
- خط 26: متد [enseignant.toString()] استفاده میشود. کلاس [Enseignant] این متد را ندارد. بنابراین، متد کلاس والد آن به طور خودکار استفاده میشود. این متد تضمین میکند که عبارت [JSON.stringify(this)] – که در آن [this] یک شی از نوع [Enseignant] خواهد بود و نه یک شی از نوع [Personne] – به درستی ارزیابی شود. این پدیده در برنامهنویسی شیءگرا با نام چندریختی کلاس (class polymorphism) شناخته میشود. این یک اصطلاح بزرگ برای جاوااسکریپت است که یک زبان شیءگرا نیست. با این حال، جاوااسکریپت در اینجا همان کاری را انجام میدهد که از آن انتظار میرود: یک معلم را به درستی نمایش میدهد؛
نتایج اجرای کد به شرح زیر است:
[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\classes\class-02.js"
enseignant= {"_nom":"Poirot","_prénom":"Hercule","_âge":66,"_discipline":"détective"} object true
- خط ۲: جاوااسکریپت به درستی تشخیص میدهد که متغیر [enseignant] از نوع [Enseignant] است؛
13.4. اسکریپت [class-03]
اسکریپت [class-03] نشان میدهد که یک کلاس فرزند میتواند ویژگیها و متدهای کلاس والد خود را بازنویسی کند. در اینجا، ما متد [toString] از کلاس والد را بازنویسی میکنیم:
// وارداتها
import Personne from './Personne';
// کلاس
class Enseignant extends Personne {
// سازنده
constructor(nom, prénom, âge, discipline) {
super(nom, prénom, âge);
this.discipline = discipline;
}
// گیرندهها و تنظیمکنندهها
get discipline() {
return this._discipline;
}
set discipline(value) {
this._discipline = value;
}
// بهزور نوشتن (override) toString
toString() {
return "[Enseignant]" + JSON.stringify(this);
}
}
// فراخوانی کلاس
function main() {
const enseignant = new Enseignant("Poirot", "Hercule", 66, "détective");
console.log("enseignant=", enseignant.toString(), typeof (enseignant), enseignant instanceof Enseignant);
}
//فراخوانی `main`
main();
نتایج اجرای کد به شرح زیر است:
[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\classes\class-03.js"
enseignant= [Enseignant]{"_nom":"Poirot","_prénom":"Hercule","_âge":66,"_discipline":"détective"} object true
13.5. اسکریپت [class-04]
اسکریپت [class-04] بار دیگر چندریختی (polymorphism) را در عمل نشان میدهد: جایی که یک تابع انتظار یک پارامتر اسمی از نوع [Personne] را دارد، میتوان یک نوع مشتقشده مانند [Enseignant] را به آن پاس داد. در واقع، به واسطهٔ مشتقسازی، نوع [Enseignant] تمام ویژگیهای نوع [Personne] را دارد.
ابتدا، نوع [Enseignant] را در ماژول [Enseignant.js] ایزوله میکنیم:
// وارداتها
import Personne from './Personne';
//کلاس
class Enseignant extends Personne {
// سازنده
constructor(nom, prénom, âge, discipline) {
super(nom, prénom, âge);
this.discipline = discipline;
}
// گیرندهها و تنظیمکنندهها
get discipline() {
return this._discipline;
}
set discipline(value) {
this._discipline = value;
}
}
//کلاس صادرشده
export default Enseignant;
- خط ۲۴: کلاس [Enseignant] صادر شده است تا اسکریپتهای دیگر بتوانند آن را وارد کنند؛
اسکریپت [class-04] به شرح زیر است:
// وارداتها
import Enseignant from './Enseignant';
import Personne from './Personne';
// تابعی که یک شخص را بهعنوان پارامتر میپذیرد
function show(personne) {
//در همه موارد
console.log("paramètre=", personne.toString(), typeof (personne));
// نمونه از Person
if (personne instanceof Personne) {
console.log("personne=", personne.toString());
}
// نمونهٔ معلم
if (personne instanceof Enseignant) {
console.log("enseignant=", personne.toString());
}
}
// فراخوانی `show` با یک معلم
show(new Enseignant("Poirot", "Hercule", 66, "détective"));
show(new Personne("Marple", "Miss", 70));
- خط ۶: تابع [show] انتظار یک نوع [Personne] یا یک نوع مشتق را دارد؛
- خط ۸: رشته پارامتر و نوع آن نمایش داده میشوند. ما [object] را پیدا خواهیم کرد؛
- خطوط ۱۰–۱۶: میتوانیم تشخیص دهیم که آیا از نوع [Personne] است یا از نوع [Enseignant]. بنابراین میتوان کد را متناسب با نوع واقعی پارامتر تطبیق داد؛
نتایج اجرای برنامه به شرح زیر است:
[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\classes\class-04.js"
paramètre= {"_nom":"Poirot","_prénom":"Hercule","_âge":66,"_discipline":"détective"} object
personne= {"_nom":"Poirot","_prénom":"Hercule","_âge":66,"_discipline":"détective"}
enseignant= {"_nom":"Poirot","_prénom":"Hercule","_âge":66,"_discipline":"détective"}
paramètre= {"_nom":"Marple","_prénom":"Miss","_âge":70} object
personne= {"_nom":"Marple","_prénom":"Miss","_âge":70}
- خطوط ۴ و ۶: جاوااسکریپت بهدرستی نوع نمونههای کلاس را تشخیص میدهد؛