আগের পর্বে আমরা Class আর Constructor শিখেছিলাম। এই পর্বে আমরা দেখব Inheritance (উত্তরাধিকার) — কীভাবে একটা ক্লাস আরেকটা ক্লাসের প্রপার্টি আর মেথড "উত্তরাধিকারসূত্রে" পেতে পারে, যাতে একই কোড বারবার লিখতে না হয়।
সমস্যাটা কী?
ধরো Pathok Ghor-এ দুই ধরনের কন্টেন্ট আছে — বই আর অডিওবুক। দুটোরই title, author আছে, কিন্তু অডিওবুকের অতিরিক্ত duration আছে। আলাদা আলাদা ক্লাস লিখলে কমন অংশটা বারবার লিখতে হয়:
// ❌ দুটো ক্লাসে একই title, author কোড বারবার লেখা হচ্ছে
class Book {
constructor(title, author) {
this.title = title;
this.author = author;
}
getInfo() {
return `${this.title} — ${this.author}`;
}
}
class Audiobook {
constructor(title, author, duration) {
this.title = title; // Book-এর সাথে ডুপ্লিকেট
this.author = author; // Book-এর সাথে ডুপ্লিকেট
this.duration = duration;
}
getInfo() {
return `${this.title} — ${this.author}`; // এখানেও ডুপ্লিকেট
}
}
extends দিয়ে সমাধান
extends কীওয়ার্ড দিয়ে একটা ক্লাস আরেকটা ক্লাসের সব প্রপার্টি ও মেথড "উত্তরাধিকারসূত্রে" পেয়ে যায়, শুধু নতুন যা লাগবে সেটুকু যোগ করলেই হয়।
class Book {
constructor(title, author) {
this.title = title;
this.author = author;
}
getInfo() {
return `${this.title} — ${this.author}`;
}
}
// ✅ Audiobook, Book-এর সবকিছু পাচ্ছে, শুধু duration নতুন
class Audiobook extends Book {
constructor(title, author, duration) {
super(title, author); // Book-এর constructor কল করা
this.duration = duration;
}
}
const book = new Book("সোনার তরী", "রবীন্দ্রনাথ ঠাকুর");
const audiobook = new Audiobook("পথের পাঁচালী", "বিভূতিভূষণ", "৪ ঘণ্টা");
console.log(book.getInfo()); // সোনার তরী — রবীন্দ্রনাথ ঠাকুর
console.log(audiobook.getInfo()); // পথের পাঁচালী — বিভূতিভূষণ (Book থেকে পাওয়া মেথড!)
console.log(audiobook.duration); // ৪ ঘণ্টা
Audiobook ক্লাসে getInfo() লেখাই হয়নি, তবুও কাজ করছে — কারণ এটা Book থেকে উত্তরাধিকারসূত্রে পেয়েছে।
super কীওয়ার্ড
super দুই জায়গায় ব্যবহার হয়:
| ব্যবহার | কাজ |
|---|---|
super(...) |
প্যারেন্ট ক্লাসের constructor কল করে (constructor-এর প্রথম লাইনে থাকতেই হয়) |
super.methodName() |
প্যারেন্ট ক্লাসের কোনো মেথড সরাসরি কল করে |
গুরুত্বপূর্ণ নিয়ম: চাইল্ড ক্লাসে constructor লিখলে, this ব্যবহার করার আগে অবশ্যই super() কল করতে হবে — নাহলে JavaScript এরর দেবে।
class Audiobook extends Book {
constructor(title, author, duration) {
this.duration = duration; // ❌ ReferenceError — super() আগে কল করতে হবে
super(title, author);
}
}
Method Override — নিজের মতো পাল্টানো
চাইল্ড ক্লাস চাইলে প্যারেন্টের কোনো মেথড নিজের মতো করে "override" (পুনর্লিখন) করতে পারে, প্রয়োজনে super.methodName() দিয়ে প্যারেন্টের ভার্সনও ব্যবহার করে নিতে পারে।
class Audiobook extends Book {
constructor(title, author, duration) {
super(title, author);
this.duration = duration;
}
// Book-এর getInfo() override করা হচ্ছে
getInfo() {
const baseInfo = super.getInfo(); // প্যারেন্টের ভার্সন কল করে ফলাফল ব্যবহার
return `${baseInfo} (${this.duration})`;
}
}
const audiobook = new Audiobook("পথের পাঁচালী", "বিভূতিভূষণ", "৪ ঘণ্টা");
console.log(audiobook.getInfo()); // পথের পাঁচালী — বিভূতিভূষণ (৪ ঘণ্টা)
এখানে super.getInfo() ব্যবহার করে পুরো লজিক আবার না লিখে শুধু প্যারেন্টের ফলাফলের সাথে নতুন তথ্য জুড়ে দেওয়া হচ্ছে — কোড পুনর্ব্যবহারের একটা সুন্দর উদাহরণ।
instanceof দিয়ে চেক করা
instanceof দিয়ে যাচাই করা যায় কোনো অবজেক্ট নির্দিষ্ট ক্লাস (বা তার প্যারেন্ট) থেকে বানানো কিনা:
console.log(audiobook instanceof Audiobook); // true console.log(audiobook instanceof Book); // true — কারণ Audiobook, Book-কে extend করেছে console.log(book instanceof Audiobook); // false — Book, Audiobook-এর instance না
লাইভ ডেমো — বেস ক্লাস বনাম চাইল্ড ক্লাস
নিচের দুটো কার্ড দেখো — একটা সাধারণ বই, একটা অডিওবুক (যেটা Book-কে extend করেছে)। দুটোরই getInfo() আছে, কিন্তু অডিওবুকেরটা একটু ভিন্ন ফলাফল দেয়।
কখন Inheritance ব্যবহার করবে (আর কখন না)
Inheritance শক্তিশালী, কিন্তু সবসময় সেরা সমাধান না। একটা সাধারণ নিয়ম — "is-a" সম্পর্ক থাকলে Inheritance ঠিক আছে (Audiobook is a Book), কিন্তু "has-a" সম্পর্কে (একটা জিনিসের ভেতরে আরেকটা জিনিস থাকা) সাধারণত composition (অবজেক্টের ভেতরে অবজেক্ট) বেশি ভালো।
// ✅ ভালো — is-a সম্পর্ক (Audiobook is a Book)
class Audiobook extends Book { /* ... */ }
// ❌ খারাপ ডিজাইন — has-a সম্পর্কের জন্য inheritance ব্যবহার করা
class Library extends Book { /* Library কোনোভাবেই "এক ধরনের" Book না! */ }
// ✅ ভালো — composition ব্যবহার করা (Library-এর ভেতরে Book-এর array থাকে)
class Library {
constructor() {
this.books = []; // has-a: Library-এর কাছে বই আছে
}
}
একটা সম্পূর্ণ উদাহরণ — কন্টেন্ট টাইপের হায়ারার্কি
চলো Pathok Ghor-এর জন্য একটা বাস্তব হায়ারার্কি বানাই — বেস Content ক্লাস, তার থেকে Book আর Article এক্সটেন্ড করা।
class Content {
constructor(title, publishDate) {
this.title = title;
this.publishDate = publishDate;
this.views = 0;
}
incrementViews() {
this.views++;
}
getSummary() {
return `"${this.title}" (${this.publishDate})`;
}
}
class Book extends Content {
constructor(title, publishDate, author, pageCount) {
super(title, publishDate);
this.author = author;
this.pageCount = pageCount;
}
getSummary() {
return `${super.getSummary()} — লেখক: ${this.author}, ${this.pageCount} পাতা`;
}
}
class Article extends Content {
constructor(title, publishDate, writer, readTimeMinutes) {
super(title, publishDate);
this.writer = writer;
this.readTimeMinutes = readTimeMinutes;
}
getSummary() {
return `${super.getSummary()} — লেখক: ${this.writer}, পড়তে লাগবে ${this.readTimeMinutes} মিনিট`;
}
}
const book = new Book("সোনার তরী", "১৮৯৪", "রবীন্দ্রনাথ ঠাকুর", 120);
const article = new Article("JavaScript শেখা", "২০২৬", "আরিফ", 8);
console.log(book.getSummary());
// "সোনার তরী" (১৮৯৪) — লেখক: রবীন্দ্রনাথ ঠাকুর, 120 পাতা
console.log(article.getSummary());
// "JavaScript শেখা" (২০২৬) — লেখক: আরিফ, পড়তে লাগবে 8 মিনিট
book.incrementViews(); // Content থেকে পাওয়া মেথড, দুটোই ব্যবহার করতে পারে
article.incrementViews();
এখানে incrementViews() শুধু Content-এ একবার লেখা হয়েছে, কিন্তু Book আর Article দুটোই এটা ব্যবহার করতে পারছে — আর প্রতিটা তার নিজের getSummary()-এ super.getSummary() দিয়ে কমন অংশটুকু পুনর্ব্যবহার করছে।
নিজে চেষ্টা করো
Exercise:
- উপরের
Contentহায়ারার্কিতে একটা তৃতীয় চাইল্ড ক্লাসVideoযোগ করো (durationMinutes প্রপার্টি সহ)। - একটা
Animalক্লাস বানাও (name, makeSound() মেথড), তারপরDogআরCatক্লাস দিয়ে extend করো, প্রতিটাতেmakeSound()override করো। instanceofব্যবহার করে চেক করোDog-এর একটা instanceAnimal-এরও instance কিনা।- ভেবে দেখো তোমার কোনো প্রজেক্টে (Mobile Khujo-তে ফোনের ব্র্যান্ড অনুযায়ী, বা Pathok Ghor-এ কন্টেন্ট টাইপ অনুযায়ী) Inheritance প্রয়োগ করা যায় কিনা।
পরের পর্বে যা থাকছে
পরের পর্বে আমরা ফিরে যাব async জগতে — localStorage দিয়ে ডেটা persist করা, এবার Class-ভিত্তিক ডেটা মডেলের সাথে মিলিয়ে কীভাবে জটিল অবজেক্ট সংরক্ষণ ও পুনরুদ্ধার করা যায় তা দেখব।