Skip to content

Chapter 21: JavaScript Class-জাভাস্ক্রিপ্ট ক্লাস

21-1: সেইম ড্রেসে class পার্টি

একটা ক্রিকেট টিমের কথা চিন্তা কর। দেখবি, সবাই একই স্টাইলের জার্সি পড়ছে। সবার কিছু নিজস্ব বৈশিষ্ট্য আছে। ব্যাটিং অর্ডার আছে। সিরিয়াল ধরে দাঁড়িয়ে গেলে সবাইকে দেখতে একটা সিমিলার ভাইভ দেয়। ওরা যে সেইম টিমের, সেটা দেখেলেই বুঝা যায়।

একইভাবে প্রোগ্রামিং করার জন্য একই টাইপের জিনিস অনেক সময় বানাইতে হয়। যেমন: তোর ওয়েবসাইট যদি অনেক অনেক মানুষ ইউজ করে, তাহলে সব মানুষ বা ইউজারের ডাটা সেইম স্টাইল বা সেইম স্ট্রাকচারের হবে। সবার নাম, ই-মেইল এড্রেস, পাসওয়ার্ড, ঠিকানা ও ফোন নাম্বার থাকবে। এইগুলার মান একেকজনের জন্য একেক রকম হবে। তবে কী কী তথ্য থাকবে, সেটা সবার জন্য সেইম থাকবে।

আপাতত একটা সিম্পল অবজেক্ট তুই বানাই ফেল। জাস্ট সেকেন্ড ব্র্যাকেট দিয়ে ভিতরে কয়েকটা প্রোপার্টি লিখে ফেল।

javascript
const player = {
  name: "Dual Lal",
  runs: 8000,
  wickets: 108,
};

তবে এই রকম যদি শত শত, হাজার হাজার, লক্ষ লক্ষ অবজেক্ট বানাতে হয়, তাহলে কে যে কোথায় কী এক্সট্রা যোগ করে ফেলছে, সেটা নিশ্চিত করা সম্ভব না। একেক জায়গায় একেকভাবে উল্টাপাল্টা করে ফেলতে পারে। এইভাবে সব অবজেক্টের মধ্যে সেইম স্ট্রাকচার নিশ্চিত করা টাফ।

আর এই কাজটাই করে class দিয়ে। ক্লাস দিয়ে নিশ্চিত করে সিমিলার টাইপের সব অবজেক্টে সেইম প্রোপার্টি আর সেইম মেথড থাকবে। সবার সেইম স্ট্রাকচার থাকবে।

class পার্টি

ক্লাস হলো একটি টেমপ্লেট, যা থেকে তুই একই টাইপের একাধিক অবজেক্ট তৈরি করতে পারবি। প্রতিটি অবজেক্টের মধ্যে একই বৈশিষ্ট্য থাকবে। ক্লাস লেখার জন্য প্রথমেই তুই class কি-ওয়ার্ড লিখবি, তারপর ক্লাসের একটা নাম দিবি। সাধারণত ক্লাসের নাম বড় হাতের অক্ষর দিয়ে শুরু করতে হয়। তারপর দুইটা সেকেন্ড ব্র্যাকেট দিবি। নিচের মতো করে—

javascript
class Player {}

ক্লাস থেকে অবজেক্ট বানানোর সময় একটা মেইন জিনিস মাথায় রাখতে হবে। ক্লাস হচ্ছে টেমপ্লেট, এইটা কিন্তু অবজেক্ট না। ক্লাস হচ্ছে একটা স্ট্রাকচার, একটা কমন শেইপ, একটা ফর্মা বা একটা মোল্ড, যেটা দিয়ে অবজেক্ট বানানো হবে। অর্থাৎ ক্লাস থেকে অবজেক্ট বানাইতে হবে। বানানোকে ইংরেজিতে construction বলে। আর এই construction যে করে, তাকে কনস্ট্রাকটর (constructor) বলে। এজন্য প্রত্যেকটা ক্লাসের ভিতরে কনস্ট্রাকটর নামে একটা স্পেশাল ফাংশন থাকে। জাস্ট দেখতে ফাংশনের মতো। এইটার আগে কোনো function কি-ওয়ার্ড থাকে না। জাস্ট constructor লিখে দিবি, আর এইটার মধ্যে যত প্যারামিটার লাগবে, সেটা নিয়ে নিবি।

javascript
class Player {
  constructor(name, runs, wickets) {}
}

ক্লাস কেন লিখে? ক্লাস লিখে একই স্টাকচারের অনেক অনেক অবজেক্ট বানানোর জন্য। এই অবজেক্ট বানানোর কাজ কে করবে? সেটা করবে এই constructor মেথড। এই constructor মেথড (ফাংশন) ডিক্লেয়ার করলেও এইটাকে সরাসরি কেউ কল করে না; বরং ক্লাস দিয়ে অবজেক্ট বানাতে গেলে ইনডাইরেক্টলি অটোমেটিকভাবে এই কনস্ট্রাকটর মেথডকে কল করা হয়ে যায়।

ক্লাস তৈরি করার সময় constructor নামে একটা মেথড ডিক্লেয়ার করে। এটা দেখতে ফাংশনের কাছাকাছি। এটাতে প্যারামিটার দেয়া যায়, ডিফল্ট মান সেট করা যায়, ফাংশনের মতো কল করা যায়। তারপরেও এইটাকে ফাংশন বলে না। এইটাকে মেথড বলে এবং এই মেথডের নাম এক্সাক্টলি constructor হতে হবে। অন্য কোনো নাম দিলে হবে না। তা ছাড়া constructor শব্দটাই এই কাজের জন্য রিজার্ভ করে রাখছে।

যা-ই হোক, এইবার কথা হচ্ছে— ক্লাস থেকে অবজেক্ট বানায় কীভাবে? বানানোর সিস্টেম খুবই সিম্পল। বামপাশে ভেরিয়েবলের মতো করে একটা নাম দিবি। তারপর ডানপাশে new লিখে ক্লাসের নাম লিখে দুইটা ব্র্যাকেট দিয়ে দিবি। যদি কনস্ট্রাকটর মেথডে কোনো প্যারামিটার থাকে, তাহলে ক্লাসের নামের পর প্যারামিটারের মতো করে সেগুলা দিতে হবে। আর যদি কনস্ট্রাকটর মেথডের কোনো প্যারামিটার না থাকে, তাহলে ক্লাসের পর ব্র্যাকেটের ভিতরে কোনো কিছু লেখা লাগবে না।

javascript
class Player {
  constructor(){
  }
}

const mushi = new Player();
console.log(mushi);

Output: Player {}

ওপরের ক্লাসে কোনো প্রোপার্টি নাই। কোনো মেথড নাই। তাই সেটা থেকে যে অবজেক্ট বানাইছি, সেটার মধ্যেও কিছু নাই। জাস্ট খালি একটা অবজেক্ট।

খালি না হয়ে ভরাট অবজেক্ট চাইলে সেটার মধ্যে দুইটা জিনিস যোগ করতে হয়। এক হচ্ছে বৈশিষ্ট্য বা প্রোপার্টি। আরেকটা হচ্ছে মেথড। সো, অবজেক্টে যদি প্রোপার্টি থাকতে হয়, তাহলে সেটা ক্লাসে থাকতে হয়। আর ক্লাসে যদি প্রোপার্টি থাকতে হয়, তাহলে সেটা constructor-এর ভিতরে লিখতে হবে এবং লেখার সময় দুইটা কাজ করতে হবে।

১) অনেকটা ভেরিয়েবল ডিক্লেয়ারের মতো করে হলেও বামপাশে this লিখে তারপর ডট চিহ্ন দিয়ে তারপর প্রোপার্টির নাম লিখতে হবে।

২) তারপর সমান চিহ্ন দিয়ে ডানপাশে হয় প্রোপার্টির মান বসিয়ে দিতে হবে। আর যদি অবজেক্ট বানানোর সময় একেক প্রোপার্টির মান একেক রকমের করতে চাস, তাহলে সেটা constructor মেথডের প্যারামিটার হিসেবে নিতে হবে এবং সেই প্যারামিটার প্রোপার্টির মান হিসেবে বসিয়ে দিতে হবে।

যতবার তুই ক্লাস থেকে অবজেক্ট তৈরি করবি, ততবার আলাদা আলাদা অবজেক্ট তৈরি করতে পারে এবং প্রত্যেকটা অবজেক্টের আলাদা আলাদা প্রোপার্টি থাকতে পারে, যাতে কারো সাথে কোনো রিলেশন না থাকে। একটা আরেকটা প্রোপার্টির মধ্যে কোনো রেফারেন্স থাকবে না।

নিচে আমি একটা ক্লাস লিখলাম তিনটা প্রোপার্টির নিয়ে। সেজন্য কনস্ট্রাকটরের মধ্যে তিনটা প্যারামিটার রাখলাম। সাধারণত প্রোপার্টির নাম আর constructor মেথডের প্যারামিটারের নাম একই থাকে। তাহলে বুঝতে সুবিধা হয়। কোন প্রোপার্টির সাথে কোন প্যারামিটারের মান বসবে।

আর আগের মতো করেই এই ক্লাস থেকে তুই অবজেক্ট বানাতে পারবি। আগের মতোই ডানপাশে new লিখে তারপর ক্লাসের নাম লিখে ফেলবি। ডিফারেন্স শুধু এখন যেহেতু কনস্ট্রাকটর মেথডে তিনটা প্যারামিটার আছে, তাই class-কে কল করার সময় তিনটা আর্গুমেন্ট দিয়ে দিতে হবে।

javascript
class Player {
  constructor(name, runs, wickets){
    this.name = name;
    this.runs = runs;
    this.wickets = wickets;
  }
}

const tam = new Player('Tam', 5000, 2);
console.log(tam);
const mash = new Player('Mash', 3200, 180);
console.log(mash);

Output:
{ name: 'Tam', runs: 5000, wickets: 2 }
{ name: 'Mash', runs: 3200, wickets: 180 }

ওপরে আমরা দুইটা ডিফারেন্ট অবজেক্ট তৈরি করেছি সেইম ক্লাস দিয়ে। দুইটার স্ট্রাকচার কিন্তু সেইম। শুধু মানগুলি আলাদা আলাদা। এইটাই ক্লাসের মজা।

অবজেক্ট তৈরি করার সময় new লিখে বুঝানো হয়, তুই ক্লাস থেকে নতুন একটা অবজেক্ট তৈরি করতে চাস।

অবজেক্টের পিতৃপরিচয়

কোনো একটা ক্লাস থেকে যতগুলা অবজেক্ট তৈরি হয়, সবগুলাকে বলা হয় ওই ক্লাসের instance। ইংরেজি instance শব্দের বাংলা মানে হচ্ছে নমুনা, নিদর্শন ইত্যাদি। অর্থাৎ কোনো ক্লাসের একটা নমুনা অবজেক্ট বানানো হয়েছে। চাইলে typeof-এর মতো করে কোনো একটা অবজেক্ট কোনো একটা ক্লাসের ইনস্ট্যান্স কি না, সেটাও চেক করা যায়।

নিচে একটা ক্লাস বানালাম FoodOrder নামে। সেখানে চারটা প্রোপার্টি আছে। তবে constructor ফাংশনে প্যারামিটার আছে তিনটা। কারণ, একটা প্রোপার্টির মান সব অবজেক্টের জন্য সেইম রাখলাম। সেটা constructor-এর ভিতরে সেট করে দিব জাস্ট দেখার জন্য। আর নিচে দুইটা অবজেক্ট বানালাম। এই ক্লাস থেকে—

javascript
class FoodOrder {
  constructor(customer, food, price ) {
    this.vendor = 'panda';
    this.customer = customer;
    this.food = food ;
    this.price = price ;
  }
}

const order1 = new FoodOrder( 'Mizan', 'Pizza', 1500);
const order2 = new FoodOrder( 'Azim', 'Burger', 1000);
console.log(order1);
console.log(order2);

Output:
{ vendor: 'panda', customer: 'Mizan', food: 'Pizza', price: 1500 }
{ vendor: 'panda', customer: 'Azim', food: 'Burger', price: 1000 }

ইনস্ট্যান্স

কোনো একটা ক্লাস থেকে যতগুলা অবজেক্ট তৈরি হয়, সবগুলাকে বলা হয় ওই ক্লাসের instance। ইংরেজি instance শব্দের বাংলা মানে হচ্ছে নমুনা, নিদর্শন ইত্যাদি। অর্থাৎ কোনো ক্লাসের একটা নমুনা অবজেক্ট বানানো হয়েছে। চাইলে typeof-এর মতো করে কোনো একটা অবজেক্ট কোনো একটা ক্লাসের ইনস্ট্যান্স কি না, সেটাও চেক করা যায়।

এখন চেক করে দেখ, order1 অবজেক্ট foodOrder-এর ইনস্ট্যান্স কি না।

javascript
console.log(order1 instanceof FoodOrder);

Output: true

একইভাবে চেক করে দেখ, একটা অন্য অবজেক্ট, সেটা FoodOrder-এর ইনস্ট্যান্স কি না।

console.log( { age: 91 } instanceof FoodOrder);

Output: false

কোনো অবজেক্ট এসে যদি বলে, আমি সেই ক্লাসের সন্তান, তাহলে তুই DNA টেস্টের মতো করে instanceOf দিয়ে ধরে ফেলতে পারবি।

Practice:

  1. ক্লাস আর অবজেক্টের মধ্যে ডিফারেন্স কী?
  2. ক্লাস ইনস্ট্যান্স বলতে কী বুঝায়?
  3. Vehicle নামে একটা class লিখ, সেখানে constructor-এর মধ্যে brand, model এবং price প্রোপার্টি রাখ। Vehicle ক্লাস থেকে দুইটা instance বানা, একটা BMW X5, যেখানে ব্র্যান্ড BMW, মডেল X5 আর price তুই তোর ইচ্ছামতো কোনো একটা দাম বসিয়ে দে। আরেকটা গাড়ির জন্য ব্র্যান্ড Tesla, মডেল Model 3 আর price 40000 ।
  4. Worker নামে একটা class বানিয়ে সেখানে id, name আর hoursWorked নামে প্রোপার্টি যোগ কর। তারপর নতুন worker বানা, যার id হবে 101, name হবে Tom Cruise আর hoursWorked হবে 40।
  5. Library নামে একটা class বানা, যেখানে constructor-এর মধ্যে তিনটা প্রোপার্টি থাকবে name, books, আর location। তারপর নতুন একটা library বানা, যার নাম Central Library, books 10000 আর location Dhaka। এরপর instanceOf দিয়ে চেক কর তোর বানানো অবজেক্টটা Library ক্লাসের ইন্সটান্স কি না।
  6. Classroom নামে একটা class বানা, যেখানে students নামে একটা প্রোপার্টি থাকবে, যা শুরুতে খালি array হবে। constructor-এর মধ্যে section আর teacher প্রোপার্টি রাখ। তারপর Classroom থেকে একটা instance বানা, যার section হবে A আর teacher হবে Mr. Plumber ।
  7. Product নামে একটা class বানা, যেখানে constructor-এর মধ্যে name, category আর stock থাকবে। তারপর নতুন একটা product বানা, যার নাম হবে Mobile, category হবে Electronics আর stock হবে 50।
  8. Product নামে একটা class বানা, যেখানে constructor-এর মধ্যে name, category আর stock থাকবে। তারপর নতুন একটা product বানা, যার নাম হবে Mobile, category হবে Electronics আর stock হবে 50। যদি অবজেক্ট বানানোর সময় কেউ stock প্রোপার্টির মান না দেয়, তাহলে stock-এর ডিফল্ট মান 0 দিয়ে দিবি।

21-2: Method তুমি কার? ক্লাসের না আমার?

অবজেক্টের কিছু বৈশিষ্ট্য থাকে এবং অবজেক্ট কিছু কাজ করে। তাই অবজেক্ট কিছু ফাংশনও। যদিও এইগুলাকে ফাংশন বলা ঠিক না। এইগুলাকে বলা হয় মেথড।

প্রথমে ঠিক আগের মতো একটা ক্লাস লিখে ফেলি। এইখানে Player ক্লাসের মধ্যে প্লেয়ারের নাম, রানসংখ্যা, উইকেটসংখ্যা আছে। চাইলে খুব সহজেই এই ক্লাস থেকে অবজেক্ট বানাতে পারবি। সেটা কোনো ব্যাপারই না তোর জন্য।

javascript
class Player {
  constructor(name, runs, wickets) {
    this.name = name;
    this.runs = runs;
    this.wickets = wickets;
  }
}

মেথড

এখন এই ক্লাসে একটা method যোগ করব (অর্থাৎ ফাংশন যোগ করব)। প্রথম মেথডের কাজ হচ্ছে, প্লেয়ারের রান কত, সেটা বলে দিবে। এই মেথডের নাম দিলাম getRun।

এই getRun মেথড লেখার জন্য অনেকটা ফাংশনের মতোই লিখবি, তবে function কি-ওয়ার্ড লিখবি না। যেমনটা তুই constructor মেথডের জন্য function কি-ওয়ার্ড লিখস নাই। সেইম হিসাব। তারপর নরমাল ফাংশনের মতো প্যারামিটার লিখবি। দরকার হলে ডিফল্ট প্যারামিটার সেট করবি এবং চাইলে নরমাল ফাংশনের মতো কাজকর্ম করতে পারবি। কনসোল করতে পারবি। কোনো কিছু রিটার্ন করতে পারবি।

ক্লাসে কোনো মেথড ডিক্লেয়ার করলে সেই মেথড ক্লাসের সব অবজেক্টে পাওয়া যাবে। জাস্ট অবজেক্টের নামের পর ডট চিহ্ন দিয়ে ফাংশনের মতো করে কল করে ফেলবি। সেই মেথডে কোনো প্যারামিটার লাগলে সেই প্যারামিটার দিয়ে দিবি।

this

ক্লাস থেকে কোনো প্রোপার্টি পাবি না। প্রোপার্টি পাবি ক্লাস থেকে অবজেক্ট বানিয়ে। আবার ক্লাস থেকে কোন মেথড পাবি না। মেথড পাবি ক্লাস থেকে অবজেক্ট বানিয়ে। তাহলে যখন ক্লাস লিখবি, সেটার ভিতরে মেথড লিখবি বা মেথডের ভিতরে কোনো প্রোপার্টির মান এক্সেস করবি বা চেইঞ্জ করবি। সেটা কীভাবে করবি?

ক্লাসের ভিতরে প্রোপার্টি বা মেথড এক্সেস বা চেইঞ্জ করার জন্য this অনেক বেশি গুরুত্বপূর্ণ (কিছুটা কনফিউজিং হলেও একটু পরে এইটার দফারফা করব)। this এমন একটা keyword, যেটা প্রতিটি object-কে বুঝায়। তাই ক্লাসের ভিতরে method বা প্রোপার্টি যেকোনোটাই এক্সেস করতে গেলে this থেকে সেটাকে এক্সেস করতে হয়।

নিচের মেথডে আমরা নরমালভাবে ক্লাসের run প্রোপার্টিকে রিটার্ন করে দিছি।

javascript
class Player {
  constructor(name, runs, wickets) {
    this.name = name;
    this.runs = runs;
    this.wickets = wickets;
  }

  getRun() {
    return this.runs;
  }
}

const player1 = new Player("Tamim", 5000, 100);
const tamimRun = player1.getRun();
console.log(tamimRun);

Output: 5000;

তুই চাইলে অবজেক্টের কোনো প্রোপার্টির মান চেইঞ্জ বা মোডিফাইও করতে পারবি। সেজন্য আমি সেই Player ক্লাসে প্লেয়ারের রান যোগ করার জন্য একটা মেথড লিখলাম। এটার নাম দিলাম addRun, সে একটা সংখ্যা ইনপুট প্যারামিটার হিসেবে নিবে, তারপর প্লেয়ার বর্তমান রানের সাথে নতুন রান যোগ করবে।

যদি অবজেক্টের প্রোপার্টির মান সেট করতে চাস, তাহলে বামপাশে this লিখে ডট চিহ্ন দিবি। এরপর যে প্রোপার্টি দরকার, তার নাম লিখে ফেলবি। এরপর সমান চিহ্নের পরে যে নতুন ভ্যালু হবে বা কোনো হিসাব করা লাগলে, সেটা করে ফেলবি। আর কিছু না।

নিচে Player থেকে অবজেক্ট বানাইছি। তারপর দুইবার addRun মেথডকে কল করে অবজেক্টের run-এর সংখ্যা বাড়াইছি। খুবই সিম্পল, আবার খুবই মজার।

javascript
class Player {
  constructor(name, runs, wickets) {
    this.name = name;
    this.runs = runs;
    this.wickets = wickets;
  }

  addRun(run) {
    this.runs = this.runs + run;
  }
}

const player1 = new Player("Tamim", 5000, 100);
player1.addRun(200);
player1.addRun(31);
console.log(player1);

Output: { name: 'Tamim', runs: 5231, wickets: 100 }

ইনস্ট্যান্স মেথড

ওপরে যে মেথড লিখছিস, সেটা হচ্ছে ক্লাস থেকে একটা ইনস্ট্যান্স বানিয়ে সেটার মধ্যে ইউজ করার মেথড। এইটা পাওয়া যায় শুধু ক্লাস থেকে new কি-ওয়ার্ড দিয়ে অবজেক্ট (ইনস্ট্যান্স) তৈরি করলে। তাই এইটাকে অনেক সময় ইনস্ট্যান্স মেথড বলে।

আরেকটা ক্লাস এইখানে লিখে ফেললাম ব্যাংক একাউন্টের জন্য। এইখানে দুইটা মেথড আছে। একটা হচ্ছে একাউন্টে টাকা ডিপোজিট করার জন্য, আরেকটা হচ্ছে টাকা withdraw (টাকা উঠানোর জন্য)। এই দুইটাই কিন্তু ইনস্ট্যান্স মেথড। ক্লাস থেকে অবজেক্ট না বানালে এইগুলাকে ইউজ করা যাবে না। তাই আমরা myAccount অবজেক্ট বানিয়ে তারপর টাকা জমা দিয়েছি, আবার টাকা উঠানোর চেষ্টা করেছি।

আর নিচের deposit মেথডে জাস্ট ইনপুট প্যারামিটার হিসেবে কত টাকা ডিপোজিট করতে চায়, সেটা নিয়েছি। তারপর সেটা দিয়ে তার ব্যাংক ব্যালেন্সের পরিমাণ বাড়িয়েছি। অন্যদিকে withdraw মেথডের ভিতরে চেক করতেছি, সে কত টাকা উঠাতে চায়। যদি তার ব্যাংক ব্যালেন্স যত আছে, তার চাইতে কম টাকা উঠাতে চায়, তাহলে সে উঠাতে পারবে। তবে তার ব্যাংক ব্যালেন্স যত টাকা আছে, তার চাইতে বেশি টাকা উঠাতে চায়, তাহলে সে টাকা পাবে না। একটা টেক্সট পাবে 'Insufficient Balance'।

javascript
class BankAccount {
  constructor(owner, balance) {
    this.owner = owner;
    this.balance = balance;
  }

  deposit(amount) {
    this.balance += amount;
    return this.balance;
  }

  withdraw(amount) {
    if (this.balance >= amount) {
      this.balance -= amount;
      return amount;
    } else {
      return 'Insufficient Balance';
    }
  }
}

const myAccount = new BankAccount('Leo', 5000);
myAccount.deposit(2000);
myAccount.withdraw(500);
console.log(myAccount);

Output: { owner: 'Leo', balance: 6500 }

Practice:

  1. হোটেলের জন্য একটা ক্লাস বানিয়ে ফেল। যেখানে হোটেলের নাম, রুমসংখ্যা এবং রাতে থাকার খরচ থাকবে। তারপর getName মেথডকে কল করলে হোটেলের নাম রিটার্ন করবে।

  2. Employee ক্লাস বানিয়ে ফেল, যেখানে থাকবে কর্মীর নাম, পদ এবং বেতন। getSalary বললে তার স্যালারি (বেতন) কত, সেটা রিটার্ন করবে।

  3. একটা ক্লাস লিখে ফেল, যেটার নাম দিবি Library। এইটার ভিতরে একটা প্রোপার্টি থাকবে books নামে, আর সেই প্রোপার্টির প্রাথমিক মান হবে একটা খালি অ্যারে। এরপর addBook নামে একটা মেথড লিখবি। সে প্যারামিটার হিসেবে একটা বইয়ের নাম নিবে। তারপর books প্রোপার্টিতে সেই বই যোগ করে দিবে। আরেকটা মেথড লিখবে hasBook নামে, সে একটা প্যারামিটার নিবে। প্যারামিটারে থাকবে বইয়ের নাম। সে গিয়ে চেক করবে, যে নাম দিয়ে বই খুজঁতেছস, সেই বই যদি books প্রোপার্টিতে থাকে, তাহলে সে true রিটার্ন করবে। আর না থাকলে সে false রিটার্ন করবে।

  4. এখন একটা ShoppingCart ক্লাস লিখে ফেল, যেখানে products নামে একটা প্রোপার্টি থাকবে, আর totalPrice নামে একটা প্রোপার্টি থাকবে। যখন এই ক্লাস থেকে অবজেক্ট বানাবি, তখন products হবে একটা খালি অ্যারে, আর totalPrice হবে 0। এরপর addToCart একটা মেথড হবে। এইটাকে কল করতে গেলে দুইটা প্যারামিটার লাগবে। একটা প্যারামিটারে থাকবে প্রোডাক্টের নাম, আরেকটা প্যারামিটার হবে প্রোডাক্টের দাম। আর এই addToCart-কে কল করলে সে প্রোডাক্টের নামকে products নামক প্রোপার্টিতে যোগ করে দিবে। আর প্রোডাক্টের দাম totalPrice নামক প্রোপার্টির আগের ভ্যালুর সাথে যোগ করে দিবে। সবার শেষে getTotalPrice নামে আরেকটা মেথড লিখে ফেল, যে টোটাল প্রাইস রিটার্ন করবে।

21-3: আজ থেকে তুই ত্যাজ্য Inheritance

বাংলা সিনেমায় অনেক সময় ডায়লগ দেয়— আজ থেকে তোকে আমি ত্যাজ্যপুত্র ঘোষণা করলাম। আমার সব সহায়-সম্পদ থেকে তোকে বঞ্চিত করলাম।

অর্থাৎ ত্যাজ্যপুত্র বা ত্যাজ্যকন্যা ঘোষণা করার মানে হচ্ছে, বাবা-মা থেকে উত্তরাধিকারসূত্রে কোনো সম্পত্তি পাবে না। উত্তরাধিকার একটা কঠিন শব্দ, এইটার কঠিন একটা ইংরেজি শব্দ আছে, সেটাকে inheritance বলে।

আপাতত বাংলা সিনেমা সাইডে রেখে প্রোগ্রামিংয়ের কথা চিন্তা কর।

একটা বড়সড় সফটওয়্যার বানাতে প্রচুর কোড লিখতে হয়। প্রচুর মানে প্রচুর। সেখানে কয়েকশত ক্লাস লিখে ফেললেও অবাক হওয়ার কিছু থাকে না। আর যদি কাছাকাছি টাইপের অনেকগুলা ক্লাস লিখতে হয়। যেমন ধর, আমার কাছে তিনটা ক্লাস আছে Laptop, Phone আর Tablet। এইগুলার শুধু প্রোপার্টি দেখাচ্ছি।

javascript
class Laptop {
  constructor(brand, model, price, keyboardLight) {
    this.brand = brand;
    this.model = model;
    this.price = price;
    this.keyboardLight = keyboardLight;
  }
}

class Phone {
  constructor(brand, model, price, hasFaceUnlock, cameraCount) {
    this.brand = brand;
    this.model = model;
    this.price = price;
    this.hasFaceUnlock = hasFaceUnlock;
    this.cameraCount = cameraCount;
  }
}

class Tablet {
  constructor(brand, model, price, hasPen) {
    this.brand = brand;
    this.model = model;
    this.price = price;
    this.hasPen = hasPen;
  }
}

তুই একটু খেয়াল করলে বুঝতে পারবি, এই তিনটা ক্লাসের মধ্যেই কিন্তু তিনটা প্রোপার্টি কমন। সবগুলারই কিন্তু brand, model, price প্রোপার্টি আছে। আর সবগুলার জন্যই বারবার এই তিনটা প্রোপার্টির নাম লেখা লাগছে। তবে তুই চাইলে এই জিনিস একবার লিখে সব ক্লাসে ইউজ করতে পারবি।

এইটার জন্য তোকে এই তিনটার কমন একটা ক্লাস লিখতে হবে। যে ক্লাসকে অনেক সময় প্যারেন্ট ক্লাস বলে। অনেকটা তোর বাবা-মার মতো। তোর বাবা-মার সম্পদ যেমন তুই উত্তরাধিকারসূত্রে পেয়ে যাস, তেমনি একইভাবে আমরা একটা কমন ক্লাস লিখতে পারি। তারপর সেই ক্লাসের সাথে আমাদের ক্লাসগুলোর একটা আংটা লাগায় ফেলতে পারি। তাহলে কমন ক্লাস বা প্যারেন্ট ক্লাসের যত প্রোপার্টি আর যত মেথড আছে, সব চাইল্ড ক্লাসগুলো পেয়ে যাবে।

এই প্যারেন্ট আর চাইল্ড রিলেশনশিপ সেট করতে চাইলে তোকে দুইটা কাজ করতে হবে এবং দুইটা স্পেশাল কি-ওয়ার্ড ইউজ করতে হবে।

এক্সটেনশন কর্ড

extends একটা ইংরেজি শব্দ, এইটার মানে হলো বাড়ানো বা বর্ধন করা। তাই একটা ক্লাস (প্যারেন্ট ক্লাস) থেকে তার প্রোপার্টি আর মেথডকে extend করা লাগবে। সেজন্য প্রথমে প্যারেন্ট ক্লাস লিখতে হয়। যার প্রোপার্টি এবং মেথড অন্য ক্লাসগুলো পাবে। তারপর চাইল্ড ক্লাস লেখার সময় চাইল্ড ক্লাসের নাম লেখার পর extends লিখে এরপর প্যারেন্ট ক্লাস লিখতে হয়। যেমন ধর, আমার প্যারেন্ট ক্লাস হচ্ছে Gadget আর চাইল্ড ক্লাস হচ্ছে Laptop, তাহলে আমি নিচের মতো করে লিখব।

javascript
class Gadget {}

class Laptop extends Gadget {}

সুপার ডুপার প্যারেন্ট

সাধারণত প্যারেন্ট ক্লাসে constructor মেথড থাকে এবং সেই constructor মেথডের ভিতরে কিছু প্রোপার্টির মান সেট করা হয়। যেগুলা সব চাইল্ড ক্লাসের জন্য কমন থাকবে। অন্যদিকে চাইল্ড ক্লাসের নিজস্ব কিছু প্রোপার্টি থাকে। তাই চাইল্ড ক্লাসে constructor-এর মধ্যে কিছু প্যারামিটার নিতে হয়। যেগুলা চাইল্ড ক্লাসে এবং প্যারেন্ট ক্লাসে প্রোপার্টির মান হিসেবে সেট করা লাগে।

চাইল্ড ক্লাসের প্রোপার্টিগুলা সহজেই সেট করে দিতে পারবি। অন্যদিকে যদি প্যারেন্ট ক্লাসের প্রোপার্টি হয়, তখন প্যারেন্ট ক্লাসের constructor-কে কল করে তাকে প্যারামিটারগুলো দিতে হবে। আর প্যারেন্ট ক্লাসের constructor-কে কল করার জন্য super নাম দিয়ে কল করতে হয়।

নিচের কোডে দেখবি, Laptop ক্লাসের নামের পর extends লিখে তারপর Gadget লেখা হয়েছে। এইটা দিয়ে বুঝা যায়, Laptop ক্লাস Gadget ক্লাসের সব প্রোপার্টি এবং মেথড পাবে এবং Laptop ক্লাসের constructor মেথডে দেখতে পাবি চারটা প্যারামিটার নিচ্ছে। এর মধ্যে তিনটা প্যারামিটার দিয়ে super মেথডকে কল করতেছে। এই তিনটা প্যারামিটার আসলে Gadget ক্লাসের প্যারামিটার। এ ছাড়া ল্যাপটপের নিজস্ব একটা প্রোপার্টি আছে keyboardLight, সেটা সে চাইল্ড ক্লাসেই সেট করে ফেলতেছে।

javascript
// Parent Class
class Gadget {
  constructor(brand, model, price) {
    this.brand = brand;
    this.model = model;
    this.price = price;
  }
}

// Child Class: Laptop
class Laptop extends Gadget {
  constructor(brand, model, price, keyboardLight) {
    super(brand, model, price);
    this.keyboardLight = keyboardLight;
  }
}

const myLaptop = new Laptop("Dell", "XPS 15", 1500, true);
console.log(myLaptop.brand);
console.log(myLaptop.model);
console.log(myLaptop.price);
console.log(myLaptop.keyboardLight);

Output:
Dell
XPS 15
1500
true

যদিও ল্যাপটপ ক্লাসের নিজস্ব কোনো ব্র্যান্ড বা প্রাইস বা মডেল প্রোপার্টি নাই। সে gadget ক্লাসের প্রোপার্টি উত্তরাধিকারসূত্রে পাচ্ছে। সেজন্য gadget হচ্ছে প্যারেন্ট ক্লাস, আর Laptop হচ্ছে চাইল্ড। সেইম প্যারেন্ট দিয়ে আমরা অনেক চাইল্ড ক্লাস বানাতে পারি। যেমন: নিচে আমরা Phone নামে আরেকটা ক্লাস লিখছি, যেটা Gadget থেকে inherit করতেছে।

javascript
class Phone extends Gadget {
  constructor(brand, model, price, hasFaceUnlock) {
    super(brand, model, price);
    this.hasFaceUnlock = hasFaceUnlock;
  }
}

const myPhone = new Phone("Apple", "iPhone 14", 999, true);
console.log(myPhone.brand);
console.log(myPhone.hasFaceUnlock);

Output: Apple;
true;

একদম সেইম সিস্টেমে তুই Tablet ক্লাসও বানাতে পারবি—

javascript
class Tablet extends Gadget {
  constructor(brand, model, price, hasPen) {
    super(brand, model, price);
    this.hasPen = hasPen;
  }
}

const myTablet = new Tablet("Samsung", "Galaxy Tab S8", 700, true);
console.log(myTablet.brand);
console.log(myTablet.hasPen);

Output: Samsung;
true;

তারমানে ইনহেরিটেন্স ইউজ করার কারণে সেইম প্রোপার্টি সব ক্লাসে লেখার দরকার পড়ে নাই। একইভাবে প্রোপার্টির মতো মেথডও প্যারেন্ট ক্লাসে থাকলে সেটা চাইল্ড ক্লাস অটোমেটিকভাবে পেয়ে যাবে।

যখন কাছাকাছি টাইপের অনেকগুলা ক্লাসের কথা চিন্তা করবি, তখন বের করার চেষ্টা করবি, কোন কোন প্রোপার্টি আর মেথডগুলা কমন, আর কোন কোন প্রোপার্টিগুলা আনকমন। কমন প্রোপার্টি আর কমন মেথডগুলা চলে যাবে প্যারেন্ট ক্লাসে। তাহলে সব ক্লাসের জন্য এই জিনিসগুলো রিপিট করা হবে না। আর আনকমন প্রোপার্টি আর মেথডগুলা থাকবে চাইল্ড ক্লাসের মধ্যে।

কারণ, কোডের মধ্যে যতসম্ভব রিপিট কমাতে হবে। সেজন্য অনেক সময় বলা হয় কোড DRY রাখবে। DRY বলতে বুঝায় Don't Repeat Yourself

Practice:

  1. ইনহেরিটেন্স কী জিনিস? এইটা কেন দরকার?

  2. প্যারেন্ট আর চাইল্ড ক্লাসের মধ্যে সম্পর্ক কীভাবে তৈরি হয়।

  3. বেশ কয়েক রকমের যানবাহনের কথা চিন্তা কর। Bus, Truck আর bike। প্রথমে এদের জন্য তোর ইচ্ছামতো (চিন্তা করে করে ) মিনিমাম 5টা করে প্রোপার্টি যোগ কর। তারপর দেখ, কোন কোন প্রোপার্টি কমন, আর কোন কোন প্রোপার্টি আনকমন। তারপর কমন প্রোপার্টিগুলা নিয়ে একটা প্যারেন্ট ক্লাস বানিয়ে ফেল। এরপর প্যারেন্ট ক্লাসকে extends করে চাইল্ড ক্লাসের সাথে রিলেশন বিল্ড কর। তারপর সবগুলা চাইল্ড ক্লাস থেকে অবজেক্ট বানিয়ে চেক করে দেখ, কমন এবং আনকমন সব ধরনের প্রোপার্টি পাচ্ছস কি না।

  4. Animal, Bird আর Fish নিয়ে চিন্তা কর। প্রত্যেকের জন্য মিনিমাম 5টা করে প্রোপার্টি বানিয়ে দেখ, কোনগুলো কমন। কমন প্রোপার্টিগুলো Parent Class-এ রাখ, আর আনকমনগুলো Child Class-এ। সবগুলো ক্লাস থেকে অবজেক্ট তৈরি করে প্রোপার্টিগুলো ঠিকঠাক কাজ করছে কি না, চেক কর।

  5. Furniture ক্লাস বানিয়ে তার চাইল্ড হিসেবে Chair আর Table তৈরি কর। কমন প্রোপার্টিগুলো Parent-এ রাখ। তারপর Chair আর Table-এর আলাদা আলাদা প্রোপার্টি আর মেথড যোগ কর।

  6. পোষা প্রাণীদের নিয়ে কাজ কর। Dog, Cat আর Parrot-এর আলাদা ক্লাস বানা। আগে Parent ক্লাস বানিয়ে কমন ফিচারগুলো সেখান থেকে ইনহেরিট কর।

  7. DRY প্রিন্সিপাল উদাহরণসহ ব্যাখ্যা কর।

21-4: Prototypical Chain-এর সিক্রেট রিলেশন

মানুষ সামাজিক জীব। সে একাকি বাস করতে পারে না। সমাজবদ্ধ হয়ে বাস করা তার জন্মগত স্বভাব। মানুষের সমাজবদ্ধতার বড় কারণ পারস্পরিক সহযোগিতা। এককভাবে কোনো মানুষই তার সমস্ত চাহিদা পূরণ করতে পারে না। বিভিন্নমুখী চাহিদার জন্য মানুষ একে অপরের ওপর নির্ভরশীল। এই বিষয়ে সমাজবিজ্ঞানী এরিস্টটল বলেন—

আচ্ছা থাক, আপাতত সমাজবিজ্ঞানী এরিস্টটল কী বলছে, সেটা একটু সাইডে রাখ।

তবে জাভাস্ক্রিপ্টের বিশেষ জ্ঞানীরা বলে— জাভাস্ক্রিপ্টের বেশির ভাগ জিনিসই অবজেক্ট। শুধু কয়েকটা প্রিমিটিভ টাইপ ছাড়া বাকিসব কিছুই অবজেক্ট। অবজেক্ট নিজে তো অবজেক্ট। এই ছাড়াও অ্যারে একধরনের অবজেক্ট, ফাংশন নিজেও একটা অবজেক্ট। set, map, promise, JSON, arguments, Date, RegEx এইগুলা সবই অবজেক্ট এবং এরা সবাই সামাজিক জীব। তারা একে অপরকে ছাড়া বাঁচতে পারে না।

তা ছাড়া একেকটা অবজেক্টও নিজেদের বিভিন্ন লেয়ার বানিয়ে রাখে, যাতে কমন জিনিসগুলো সবাই শেয়ার করতে পারে। এই শেয়ার করার প্রসেস হচ্ছে inheritance বা উত্তরাধিকার। জাভাস্ক্রিপ্ট নিজে নিজে প্রোটোটাইপিক্যাল ইনহেরিটেন্স (prototypical inheritance)-এর মাধ্যমে এক একটা অবজেক্টের মধ্যে সিক্রেট রিলেশন তৈরি করে। যাতে এক অবজেক্ট আরেক অবজেক্টের প্রোপার্টি আর মেথড শেয়ার করতে পারে। আর এই জিনিসটা ভিতরে ভিতরে জাভাস্ক্রিপ্ট করে "prototype chain"-দিয়ে।

অবজেক্টের সিক্রেট প্রোপার্টি

জাভাস্ক্রিপ্টের প্রত্যেকটা অবজেক্টের ভিতরে একটা "hidden link" থাকে, যেই লিঙ্ক দিয়ে সে অবজেক্টের সাথে কানেকশন তৈরি করে। এই ইন্টারনাল প্রোপার্টি হচ্ছে [[Prototype]]। এটা জাভাস্ক্রিপ্টের ভিতরের জিনিস। সরাসরি তুই এই [[Prototype]] দেখতে পারবি না। কারণ, এটা জাভাস্ক্রিপ্টের ইঞ্জিনের জন্য থাকে। তবে এইটার মান আমরা দুইভাবে পাইতে পারি—

১. অবজেক্টের নামের পর proto (দুইটা আন্ডারস্কোর চিহ্ন, তারপর proto-এর পর দুইটা আন্ডারস্কোর চিহ্ন) এই জিনিস ইদানিংকালে বেশি ইউজ করা হয় না।

২. সেইম জিনিস পাওয়ার জন্য আরও ভালো অপশন হচ্ছে, Object লিখে তারপর ডট চিহ্ন দিয়ে getPrototypeOf লিখে ব্র্যাকেটের মধ্যে যে অবজেক্টের prototype পেতে চাস, সেই অবজেক্টের নাম দিয়ে দিবি এইভাবে Object.getPrototypeOf(obj) । এইটা এখন বেশি ইউজ হয়।

অর্থাৎ জাভাস্ক্রিপ্ট অবজেক্টের সিক্রেট প্রোপার্টি [[Prototype]] দিয়ে সে অন্য অবজেক্ট বা তার প্রোটোটাইপের সাথে লিঙ্ক করে।

প্রোটোটাইপ চেইন

JavaScript-এ প্রত্যেক অবজেক্টের একটা প্রোটোটাইপ থাকে, এই প্রোটোটাইপ অন্য আরেকটা অবজেক্টের সাথে কানেকশন তৈরি করে। তুই যখন কোনো একটা অবজেক্টের কোনো প্রোপার্টি বা মেথড অ্যাক্সেস করার চেষ্টা করবি, সে প্রথমে সেই অবজেক্টের মধ্যে সেই প্রোপার্টি বা মেথড খুঁজবে। যদি পেয়ে যায়, তাহলে সেটা তোকে দিয়ে দিবে। আর যদি না পায়, তখন সে চেইন ধরে ওপরে উঠা শুরু করবে।

এই ওপরে উঠার সিস্টেম হচ্ছে— কোনো মেথড বা প্রোপার্টি না পেলে সে সেই অবজেক্টের প্রোটোটাইপের কাছে যাবে। সেই প্রোটোটাইপ নিজেও কিন্তু আরেকটা অবজেক্ট। সেটার মধ্যে সেই সেই প্রোপার্টি বা মেথড খোঁজে। যদি পেয়ে যায়, তাহলে দিয়ে দিবে। আর যদি না পায়, তাহলে সেই অবজেক্টের প্রোটোটাইপে গিয়ে খুঁজবে।

এভাবে একটা অবজেক্ট থেকে তার প্রোটোটাইপ ধরে ধরে ওপরের অবজেক্টে খুঁজতে থাকবে। পেয়ে গেলে তো হয়ে গেল, আর না পেলে ওপরের দিকে উঠতেই থাকবে। একটা সময় গিয়ে দেখবে, আর কোনো প্রোটোটাইপ নাই। প্রোটোটাইপ অবজেক্ট একসময় গিয়ে null হয়ে গেছে। তখন সে ওই প্রোপার্টি নাই বা মেথড নাই, সেটা বলে দিবে।

এইটাই হচ্ছে জাভাস্ক্রিপ্টের প্রোটোটাইপিক্যাল ইনহেরিটেন্সের রহস্য।

চেইন ধরে মারো টান

ধর, আমি খুবই নিষ্পাপ একটা অবজেক্ট বানালাম। এইটার মধ্যে জাস্ট একটা প্রোপার্টি আছে name নামে, আর কিচ্ছু নাই। কসম করে বলতেছি, আর কিচ্ছু নাই। জাভাস্ক্রিপ্ট এইটার মধ্যে নিজে নিজে প্রোটোটাইপ সেট করে দিছে। তুই চাইলে কনসোল লগ করে দেখতে পারবি। আরেকটা অবজেক্ট, সেটার মধ্যে অনেক অনেক প্রোপার্টি আর মেথড আছে। আমি জাস্ট কয়েকটা নিচে দেখলাম।

javascript
const mouse = {
    name: 'Jerry not Tom'
}

console.log(mouse.__proto__)

Output:
constructor: ƒ Object()
hasOwnProperty: ƒ hasOwnProperty()
isPrototypeOf: ƒ isPrototypeOf()
toString: ƒ toString()
__proto__: (...)

আরেকবার অবজেক্টের দিকে খেয়াল কর। খুবই সিম্পল আর নিষ্পাপ অবজেক্ট। জাস্ট একটা প্রোপার্টি আছে name নামে। কোনো মেথড নাই। এখন তুই যদি mouse.toString লিখে ফেলস, তাহলে এই toString কই থেকে আসবে? হাওয়া থেকে আসবে? মোটেও না; বরং সেটা আসবে mouse.proto থেকে। এইটা তুই সেট করে দিস নাই। এইটা জাভাস্ক্রিপ্ট ভিতরে ভিতরে সেট করে দেয়।

javascript
const mouse = {
    name: 'Jerry not Tom'
}
console.log(mouse.toString())

Output: '[object Object]'

তোর অবজেক্টের মধ্যে toString নাই, তারপরেও সেটা পেয়ে গেছস। কারণ, mouse অবজেক্টের প্রোটোটাইপের মধ্যে toString ছিল। আবার তুই যদি mouse.friend খুঁজিস, সেটা কিন্তু পাবি না। কেন পাবি না। কারণ, সে প্রথম মেইন অবজেক্টের মধ্যে খুঁজবে। না পেলে mouse.__proto__ এর মধ্যে খুঁজবে। সেখানে না পেলে mouse.__proto__ এর __proto__ অর্থাৎ mouse.__proto__.__proto__ কে যখন খুঁজবে, তখন দেখবে mouse.__proto__.__proto__ হচ্ছে null আর তখন বলে দিবে, এইটা নাই। কারণ, সে পুরা প্রোটোটাইপ চেইন খুঁজে দেখছে, কোথাও এইটা নাই।

console.log(mouse.__proto__.__proto__)

Output: null

extends আর super-এর ইনহেরিটেন্স

তুই যখন একটা প্যারেন্ট ক্লাসকে extend করে চাইল্ড ক্লাস বানাস, তখন কিন্তু ভিতরে ভিতরে চাইল্ড ক্লাস থেকে যে অবজেক্ট বানানো হবে, তার প্রোটোটাইপ হিসেবে প্যারেন্ট ক্লাসের অবজেক্টকে সেট করে ফেলস। এইটা তুই ওপরে ওপরে বুঝবি না। ভিতরে ভিতরে হয়ে যাবে। তবে তুই চাইলে দেখে নিতে পারস।

প্রথমে তুই ভদ্রভাবে একটা প্যারেন্ট ক্লাস আর একটা চাইল্ড ক্লাস বানিয়ে ফেল। প্যারেন্ট ক্লাসের নাম দিবি Vehicle, আর চাইল্ড ক্লাসের নাম দিবি Bus। এই দুইটার মধ্যে ইনহেরিটেন্স কাজ করবে। এরপর তুই একটা bus অবজেক্ট বানিয়ে ফেলবি। সেই অবজেক্টের নাম দিলি cityBus, আর সবার শেষে দুইভাবে চেক করে দেখ, cityBus-এর প্রোটোটাইপে কে আছে। একবার চেক কর Object.getPrototypeOf(cityBus) দিয়ে আবার চেক কর cityBus.proto দিয়ে । দুইটাই দেখবি Vehicle-কে বুঝাচ্ছে।

javascript
class Vehicle {
  constructor(brand, model, fuelType) {
    this.brand = brand;
    this.model = model;
    this.fuelType = fuelType;
  }
}

// Child Class: Bus
class Bus extends Vehicle {
  constructor(brand, model, fuelType, capacity) {
    super(brand, model, fuelType);
    this.capacity = capacity;
  }
}
const cityBus = new Bus("Volvo", "B11R", "Diesel", 50);
const proto1 = Object.getPrototypeOf(cityBus);
console.log(proto1);
const proto2 = cityBus.__proto__;
console.log(proto2);

Output:
Vehicle { }
Vehicle { }

আগে গেলে বাঘে খায়

একটু আগে দেখছিলি, mouse অবজেক্টের ওপরে toString করলে সে তার প্রোটোটাইপের toString ইউজ করে। তুই এইটা জানস, তুই যদি mouse অবজেক্টের ওপরে toString মেথড খুঁজস, তাহলে সে প্রথমে mouse অবজেক্টে খুঁজবে, না পেলে সে তার প্রোটোটাইপে যাবে। তাইলে তুই একটা চালাকি করতে পারস। তুই চাইলে তোর mouse অবজেক্টের মধ্যেই একটা toString মেথড লিখে দিতে পারস। তাহলে জাভাক্রিপ্ট mouse-এর মধ্যে toString পেয়ে গেলে সে আর প্রোটোটাইপে খুঁজতে যাবে না।

javascript
const mouse = {
    name: 'Jerry not Tom',
    toString: function() {
        return `This is a mouse named: ${this.name}`;
    }
};

console.log(mouse.toString());

Output: This is a mouse named: Jerry not Tom

এইভাবে তুই চাইলে জাভাস্ক্রিপ্টের কোনো বিল্ট-ইন মেথডকে নিজের মতো করে কাস্টমাইজ করে নিতে পারবি। এমনকি প্যারেন্ট ক্লাসে কোনো প্রোপার্টি বা মেথড থাকলেও দরকার হলে চাইল্ড ক্লাসে ইচ্ছামতো কাস্টমাইজ করে নিতে পারবি।

প্রোটোটাইপ ইনহেরিটেন্সের মূল পয়েন্ট

প্রতিটি অবজেক্টের প্রোটোটাইপ থাকে: JavaScript-এ প্রতিটি অবজেক্টের একটা অভ্যন্তরীণ লিঙ্ক থাকে, যাকে প্রোটোটাইপ বলা হয়। এটা অন্য একটা অবজেক্টের রেফারেন্স।

প্রোপার্টি খোঁজা প্রোটোটাইপ চেইনের মাধ্যমে হয়: যখন কোনো অবজেক্টে কোনো প্রোপার্টি বা মেথড খুঁজিছ, তা প্রথমে সেই অবজেক্টে খুঁজে। যদি পায়, তাহলে সেটাকে দিয়ে দেয়। আর না পেলে সেটার প্রোটোটাইপে গিয়ে খুঁজে। সেখানে না পেলে সে প্রোটোটাইপের চেইন ধরে এগুতে থাকে, যতক্ষণ পর্যন্ত প্রোটোটাইপ null না হয়।

Object.create(): একটা সময় Object.create দিয়ে প্রোটোটাইপিক্যাল ইনহেরিটেন্স সেট করা হতো। তখন Object.create লিখে সেটার মধ্যে আরেকটা অবজেক্ট দিয়ে দিলে এই দুইটার মধ্যে একটা ইনহেরিটেন্স তৈরি হয়ে যেত। তবে ES6-এ class, extends, super এইসব আসার পর আর কেউ Object.create দিয়ে ইনহেরিটেন্স তৈরি করে না।

Practice:

  1. জাভাস্ক্রিপ্টে ইনহেরিটেন্স কীভাবে কাজ করে?

  2. প্রোটোটাইপিক্যাল ইনহেরিটেন্স কী জিনিস?

  3. একটা person অবজেক্ট বানিয়ে ফেল, যেটাতে শুধু name প্রোপার্টি আছে। এখন চেক কর, এর প্রোটোটাইপে কিছু আছে কি না। থাকলে সেখান থেকে যেকোনো একটা মেথড ইউজ করে দেখ, কী আউটপুট দেখায়।

  4. তুই student নামে একটা অবজেক্ট বানাইলি। এই অবজেক্টের মধ্যে কোনো toString নামে মেথেড লিখলি না। তাহলে তুই কি student.toString() ইউজ করতে পারবি? কেন পারবি?

Released under the MIT License.