Lesson ৭ মিনিট পড়া

ইনহেরিট্যান্স এবং পলিমরফিজম (Inheritance & Polymorphism)

আগে থেকে যা তৈরি আছে, তার ওপর ভিত্তি করে নতুন কিছু তৈরি করুন

ইনহেরিট্যান্স — শূন্য থেকে শুরু করার দরকার নেই (Inheritance — Don't Start from Scratch)

কল্পনা করুন আপনি Vehicle বা যানজট নামের দারুণ একটি ক্লাস তৈরি করেছেন। এখন আপনার Car (গাড়ি), Truck (ট্রাক) এবং Motorcycle (মোটরসাইকেল) তৈরি করতে হবে। এগুলোর সবকটিতেই ইঞ্জিন আছে, গতি আছে এবং এরা চলতে পারে — তবে প্রতিটিরই নিজস্ব কিছু বাড়তি বৈশিষ্ট্য রয়েছে। আপনি কি ওই একই কোড তিনবার লিখবেন? একদমই না!

ইনহেরিট্যান্স (Inheritance) নতুন একটি ক্লাসকে (যাকে চাইল্ড বা সাবক্লাস বলা হয়) আগে থেকে থাকা কোনো একটি ক্লাসের (যাকে প্যারেন্ট বা সুপারক্লাস বলা হয়) ফিল্ড এবং মেথডগুলো স্বয়ংক্রিয়ভাবে বা নিজে থেকে পেয়ে যাওয়ার সুযোগ দেয়। এরপর চাইল্ড ক্লাসটি তার নিজের মতো করে নতুন কিছু যোগ করতে পারে অথবা ইনহেরিট করে পাওয়া মেথডগুলোকে পরিবর্তন করে নিতে পারে।

জাভাতে এর জন্য extends কিওয়ার্ড ব্যবহার করা হয়। একটি চাইল্ড ক্লাস কেবল একটিমাত্র প্যারেন্টকেই এক্সটেন্ড (extend) করতে পারে (এটি সিঙ্গেল ইনহেরিট্যান্স বা single inheritance)।

extends ব্যবহার করে বেসিক বা সাধারণ ইনহেরিট্যান্স

public class Main {
static class Animal {
String name;
int age;
Animal(String name, int age) {
this.name = name;
this.age = age;
}
void eat() {
System.out.println(name + " is eating.");
}
void describe() {
System.out.println(name + " is " + age + " years old.");
}
}
// Dog IS-AN Animal — it inherits everything
static class Dog extends Animal {
String breed;
Dog(String name, int age, String breed) {
super(name, age); // call the parent constructor
this.breed = breed;
}
void fetch() {
System.out.println(name + " fetches the ball!");
}
}
static class Cat extends Animal {
Cat(String name, int age) {
super(name, age);
}
void purr() {
System.out.println(name + " purrs... rrrrr");
}
}
public static void main(String[] args) {
Dog buddy = new Dog("Buddy", 4, "Labrador");
buddy.describe(); // inherited from Animal
buddy.eat(); // inherited from Animal
buddy.fetch(); // Dog's own method
Cat whiskers = new Cat("Whiskers", 7);
whiskers.describe();
whiskers.purr();
}
}
Output
Buddy is 4 years old.
Buddy is eating.
Buddy fetches the ball!
Whiskers is 7 years old.
Whiskers purrs... rrrrr

মেথড ওভাররাইড করা এবং পলিমরফিজম (Method Overriding & Polymorphism)

ওভাররাইডিং (Overriding) মানে হলো, যখন একটি চাইল্ড ক্লাস ইনহেরিট করে পাওয়া মেথডের নিজের মতো করে একটি আলাদা সংস্করণ বা ভার্সন তৈরি করে। ধরুন, প্যারেন্ট ক্লাসের একটি speak() মেথড আছে যা বলে "...", কিন্তু ডগ (Dog) সেটিকে ওভাররাইড করে পরিবর্তন করে বলে "উফ! (Woof!)" এবং ক্যাট (Cat) ওটিকে ওভাররাইড করে বলে "মিয়াও! (Meow!)"।

পলিমরফিজম (Polymorphism) হলো সেই দারুণ জাদুটি, যা তখনই ঘটে যখন আপনি কোনো চাইল্ড অবজেক্টকে ধরে রাখার জন্য প্যারেন্ট টাইপ (parent type) ব্যবহার করেন। আপনি একটি Animal ভ্যারিয়েবলের ওপর speak() কল করতে পারেন, এবং অবজেক্টটি আসলে কী, তার ওপর ভিত্তি করে জাভা নিজে থেকেই সঠিক সংস্করণটি বেছে নেয় বা কল করে। এটি অনেকটা একদল মিউজিশিয়ানকে "পারফর্ম করো!" বলার মতো — প্রতিটি মিউজিশিয়ান তখন নিজের নিজের বাদ্যযন্ত্রটাই বাজায়।

জাভাতে (এবং অন্যান্য ডেভেলপারদের) এটা বোঝাতে @Override অ্যানোটেশন (annotation) ব্যবহার করবেন যে, আপনি ইচ্ছাকৃতভাবেই প্যারেন্ট ক্লাসের কোনো মেথডকে পরিবর্তন বা ওভাররাইড করছেন। এটি যেকোনো বানান ভুল ধরতেও সাহায্য করে — আপনি যদি মেথডের নাম ভুল লেখেন, তবে কম্পাইলার (compiler) আপনাকে সতর্ক করে দেবে।

ওভাররাইডিং এবং পলিমরফিজম (Overriding & Polymorphism)

public class Main {
static class Shape {
String color;
Shape(String color) {
this.color = color;
}
double area() {
return 0; // default — shapes need to override this
}
void describe() {
System.out.printf("%s shape with area %.2f%n", color, area());
}
}
static class Circle extends Shape {
double radius;
Circle(String color, double radius) {
super(color);
this.radius = radius;
}
@Override
double area() {
return Math.PI * radius * radius;
}
}
static class Rectangle extends Shape {
double width, height;
Rectangle(String color, double width, double height) {
super(color);
this.width = width;
this.height = height;
}
@Override
double area() {
return width * height;
}
}
public static void main(String[] args) {
// Polymorphism: parent type, child objects
Shape[] shapes = {
new Circle("Red", 5),
new Rectangle("Blue", 4, 6),
new Circle("Green", 3)
};
for (Shape s : shapes) {
s.describe(); // Java calls the RIGHT area() for each!
}
}
}
Output
Red shape with area 78.54
Blue shape with area 24.00
Green shape with area 28.27

অ্যাবস্ট্রাক্ট ক্লাস (Abstract Classes)

public class Main {
// Abstract class — can't create instances directly
static abstract class Appliance {
String brand;
Appliance(String brand) {
this.brand = brand;
}
// Abstract method — child MUST implement this
abstract void turnOn();
// Regular method — child inherits this as-is
void showBrand() {
System.out.println("Brand: " + brand);
}
}
static class Toaster extends Appliance {
Toaster(String brand) {
super(brand);
}
@Override
void turnOn() {
System.out.println("Toaster glows orange. Toast incoming!");
}
}
static class Blender extends Appliance {
Blender(String brand) {
super(brand);
}
@Override
void turnOn() {
System.out.println("VRRRRRR! Blender is blending!");
}
}
public static void main(String[] args) {
// Appliance a = new Appliance("X"); // ERROR! Can't instantiate abstract
Appliance t = new Toaster("KitchenPro");
Appliance b = new Blender("BlendMax");
t.showBrand();
t.turnOn();
b.showBrand();
b.turnOn();
}
}
Output
Brand: KitchenPro
Toaster glows orange. Toast incoming!
Brand: BlendMax
VRRRRRR! Blender is blending!
Note: আপনার ইনহেরিট্যান্স ব্যবহার করা উচিত কি না, তা বুঝতে "IS-A (এটি কি একটি?)" পরীক্ষাটি ব্যবহার করুন। একটি কুকুর (Dog) কি একটি প্রাণী (Animal/IS-A Animal)? হ্যাঁ — তাহলে extends ব্যবহার করুন। একটি গাড়ি (Car) কি একটি ইঞ্জিন (Engine/IS-A Engine)? না — একটি গাড়ির ভেতরে একটি ইঞ্জিন থাকে (HAS-A engine)। এই ধরনের "has-a" সম্পর্কের ক্ষেত্রে, আপনাকে ফিল্ড (field) ব্যবহার করতে হবে। ইনহেরিট্যান্সের অপব্যবহার বা ভুল ব্যবহার সবচেয়ে পরিচিত বা সাধারণ ডিজাইনের ভুলগুলোর অন্যতম।
চ্যালেঞ্জ

ছোট কুইজ

কনস্ট্রাক্টরের ভেতর 'super' কিওয়ার্ডটি কী কাজ করে?
Classes & ObjectsInterfaces & Abstract Classes