স্কালা একটি অবজেক্ট-অরিয়েন্টেড প্রোগ্রামিং (OOP) ভাষা, যা সম্পূর্ণ অবজেক্ট ভিত্তিক এবং এর মধ্যে ক্লাস, অবজেক্ট, ইনহেরিটেন্স, পলিমরফিজম, অ্যাবস্ট্রাকশন, এবং এনক্যাপসুলেশন এর মতো OOP এর সমস্ত মূল ধারণা অন্তর্ভুক্ত রয়েছে। স্কালার OOP বৈশিষ্ট্যগুলো স্কালার শক্তি এবং নমনীয়তার জন্য গুরুত্বপূর্ণ ভূমিকা পালন করে।
এখানে স্কালার অবজেক্ট-অরিয়েন্টেড প্রোগ্রামিং এর কিছু গুরুত্বপূর্ণ ধারণা এবং উদাহরণ দেওয়া হল।
১. ক্লাস (Class)
স্কালায় ক্লাস তৈরি করতে class কিওয়ার্ড ব্যবহার করা হয়। ক্লাসের মধ্যে ফিল্ড, মেথড এবং কনস্ট্রাক্টর থাকতে পারে। ক্লাসে সাধারণত একটি বা একাধিক অবজেক্ট তৈরি করা হয়।
উদাহরণ:
class Person(var name: String, var age: Int) {
def greet(): Unit = {
println(s"Hello, my name is $name and I am $age years old.")
}
}
val person = new Person("Alice", 30)
person.greet() // Output: Hello, my name is Alice and I am 30 years old.এখানে:
Personএকটি ক্লাস যা দুটি ভ্যারিয়েবলnameএবংageধারণ করে।greetএকটি মেথড যাnameএবংageব্যবহার করে একটি বার্তা প্রিন্ট করে।
২. অবজেক্ট (Object)
স্কালা একটি সিঙ্গলটন অবজেক্ট হিসাবে কাজ করে, অর্থাৎ আপনি যখন object কিওয়ার্ড ব্যবহার করেন, তখন এটি একটি একক ইনস্ট্যান্স তৈরি করে। স্কালায় object একক কপি তৈরি করে এবং একাধিকবার ব্যবহার করা যায় না।
উদাহরণ:
object MySingleton {
def greet(): Unit = {
println("Hello from Singleton!")
}
}
MySingleton.greet() // Output: Hello from Singleton!এখানে:
MySingletonএকটি অবজেক্ট যাgreetমেথড ধারণ করে। একবার অবজেক্ট তৈরি হলে, তা পুনরায় ইনস্ট্যান্স করা যায় না।
৩. ইনহেরিটেন্স (Inheritance)
স্কালায় ইনহেরিটেন্সের মাধ্যমে একটি ক্লাস অন্য ক্লাস থেকে বৈশিষ্ট্য অর্জন করতে পারে। ক্লাসের মধ্যে extends কিওয়ার্ড ব্যবহার করে ইনহেরিটেন্স তৈরি করা হয়।
উদাহরণ:
class Animal(val name: String) {
def speak(): Unit = {
println(s"Animal name is $name")
}
}
class Dog(name: String) extends Animal(name) {
def bark(): Unit = {
println(s"$name says Woof!")
}
}
val dog = new Dog("Rex")
dog.speak() // Output: Animal name is Rex
dog.bark() // Output: Rex says Woof!এখানে:
Dogক্লাসAnimalক্লাস থেকে ইনহেরিট করেছে এবংbarkনামক একটি নতুন মেথড যোগ করেছে।
৪. পলিমরফিজম (Polymorphism)
স্কালায় পলিমরফিজমের মাধ্যমে একই মেথড বিভিন্ন ধরনের অবজেক্টের জন্য বিভিন্নভাবে কাজ করতে পারে। এটি মেথড ওভাররাইডিং এবং মেথড ওভারলোডিং এর মাধ্যমে অর্জিত হয়।
উদাহরণ (মেথড ওভাররাইডিং):
class Animal {
def speak(): Unit = {
println("Animal speaks")
}
}
class Dog extends Animal {
override def speak(): Unit = {
println("Dog barks")
}
}
val animal = new Animal()
val dog = new Dog()
animal.speak() // Output: Animal speaks
dog.speak() // Output: Dog barksএখানে:
Dogক্লাসspeakমেথডটিAnimalক্লাস থেকে ওভাররাইড করেছে এবং একটি নতুন বাস্তবায়ন প্রদান করেছে।
৫. এনক্যাপসুলেশন (Encapsulation)
এনক্যাপসুলেশন হল ক্লাসের অভ্যন্তরীণ ডেটা এবং মেথডগুলিকে সুরক্ষিত রাখা, যাতে বাহ্যিক কোডের সঙ্গে সরাসরি যোগাযোগ না হয়। স্কালায় এটি private এবং protected অ্যাক্সেস মডিফায়ার ব্যবহার করে অর্জিত হয়।
উদাহরণ:
class BankAccount(private var balance: Double) {
def deposit(amount: Double): Unit = {
if (amount > 0) balance += amount
}
def withdraw(amount: Double): Unit = {
if (amount <= balance) balance -= amount
}
def getBalance(): Double = balance
}
val account = new BankAccount(1000)
account.deposit(500)
account.withdraw(200)
println(account.getBalance()) // Output: 1300এখানে:
balanceভ্যারিয়েবলটিprivateকরা হয়েছে, যার ফলে এটি সরাসরি বাহ্যিক কোড থেকে অ্যাক্সেস করা যায় না। তবেdepositএবংwithdrawমেথডগুলির মাধ্যমে এটি পরিবর্তন করা যায়।
৬. অ্যাবস্ট্রাকশন (Abstraction)
স্কালায় অ্যাবস্ট্রাকশন প্রদান করা হয় abstract কিওয়ার্ডের মাধ্যমে। এটি একটি ক্লাসের মধ্যে এমন বৈশিষ্ট্য প্রকাশ করতে সহায়তা করে যা সাবক্লাস দ্বারা বাস্তবায়ন করা যাবে।
উদাহরণ:
abstract class Animal {
def sound(): Unit // Abstract method
}
class Dog extends Animal {
def sound(): Unit = {
println("Woof!")
}
}
val dog = new Dog()
dog.sound() // Output: Woof!এখানে:
Animalএকটি abstract class, যেখানেsoundমেথডটি অ্যাবস্ট্রাক্ট হিসেবে ডিফাইন করা হয়েছে এবংDogক্লাস এই মেথডের বাস্তবায়ন প্রদান করেছে।
সারাংশ
স্কালা অবজেক্ট-অরিয়েন্টেড প্রোগ্রামিং ভাষা হিসেবে জাভার মতো বিভিন্ন OOP বৈশিষ্ট্য সমর্থন করে। এর মধ্যে ক্লাস, অবজেক্ট, ইনহেরিটেন্স, পলিমরফিজম, এনক্যাপসুলেশন এবং অ্যাবস্ট্রাকশন এর মতো OOP ধারণাগুলি ব্যবহৃত হয়। স্কালার OOP বৈশিষ্ট্যগুলি একটি প্রোগ্রামারকে ক্লিন, কার্যকরী এবং পুনঃব্যবহারযোগ্য কোড লেখার সুযোগ প্রদান করে, যা সফটওয়্যার ডেভেলপমেন্টকে আরও সহজ এবং উন্নত করে।
স্কালার ক্লাস এবং অবজেক্ট উভয়ই গুরুত্বপূর্ণ বৈশিষ্ট্য এবং এটি একটি অবজেক্ট-অরিয়েন্টেড প্রোগ্রামিং ভাষা হওয়ার কারণে, স্কালায় সব কিছুই অবজেক্টের সাথে সম্পর্কিত। এই অধ্যায়ে, আমরা স্কালার ক্লাস এবং অবজেক্ট সম্পর্কে বিস্তারিতভাবে আলোচনা করব।
১. স্কালা ক্লাস (Scala Class)
স্কালায় ক্লাস একটি ব্লুপ্রিন্ট বা টেমপ্লেট হিসেবে কাজ করে, যার মধ্যে ডাটা (অ্যাট্রিবিউট) এবং মেথড (অ্যাকশন) সংরক্ষিত থাকে। ক্লাস ডিফাইন করার জন্য class কিওয়ার্ড ব্যবহার করা হয়।
ক্লাস ডেফিনিশন:
class ClassName {
// class body
}উদাহরণ: সাধারণ ক্লাস
class Person(val name: String, val age: Int) {
def greet(): Unit = {
println(s"Hello, my name is $name and I am $age years old.")
}
}
val person1 = new Person("Alice", 30)
person1.greet() // Output: Hello, my name is Alice and I am 30 years old.এখানে:
Personক্লাসের দুটি প্যারামিটার রয়েছে:nameএবংage, যেগুলিval(immutable) দিয়ে ডিফাইন করা হয়েছে।greetমেথডের মাধ্যমে আমরাnameএবংageআউটপুট হিসেবে প্রিন্ট করছি।new Person(...)দিয়ে ক্লাসের ইনস্ট্যান্স তৈরি করা হয়।
২. স্কালা অবজেক্ট (Scala Object)
স্কালার অবজেক্ট একটি একক ইনস্ট্যান্স, যা ক্লাসের মতো কাজ করে তবে শুধুমাত্র একটি অবজেক্ট থাকে। অবজেক্ট মূলত singleton ক্লাস, অর্থাৎ এর একমাত্র একটি ইনস্ট্যান্স থাকে। স্কালার অবজেক্ট সাধারণত এক্সিকিউটেবল কোডের জন্য ব্যবহৃত হয় এবং সাধারণত main মেথড থাকে যেখানে প্রোগ্রামটি শুরু হয়।
অবজেক্ট ডেফিনিশন:
object ObjectName {
// object body
}উদাহরণ: সাধারণ অবজেক্ট
object HelloWorld {
def main(args: Array[String]): Unit = {
println("Hello, Scala Object!")
}
}এখানে:
HelloWorldএকটি অবজেক্ট, যার মধ্যেmainমেথড রয়েছে।- অবজেক্টটি একবারই তৈরি হয় এবং এটি প্রোগ্রাম শুরু করার জন্য ব্যবহৃত হয়।
- স্কালায় object কিওয়ার্ডের মাধ্যমে একটি একক ইনস্ট্যান্স তৈরি হয়, যার মাধ্যমে আপনি কোডের কার্যকরী অংশ সম্পাদন করতে পারেন।
৩. ক্লাস এবং অবজেক্টের পার্থক্য
| পার্থক্য | ক্লাস (Class) | অবজেক্ট (Object) |
|---|---|---|
| ইনস্ট্যান্স | ক্লাস থেকে একাধিক ইনস্ট্যান্স তৈরি করা যায় | একমাত্র একটি ইনস্ট্যান্স থাকে |
| সংজ্ঞা | class কিওয়ার্ড দিয়ে ডিফাইন করা হয় | object কিওয়ার্ড দিয়ে ডিফাইন করা হয় |
| ব্যবহার | অবজেক্ট তৈরি করার জন্য ক্লাস ব্যবহার করা হয় | একমাত্র ইনস্ট্যান্সের মাধ্যমে কাজ সম্পাদন করা হয় |
| স্টেট | ক্লাসের মধ্যে স্টেট থাকতে পারে | অবজেক্টের মধ্যে একটি একক ইনস্ট্যান্স থাকে |
| ইনস্ট্যান্স তৈরি | new ClassName ব্যবহার করে ইনস্ট্যান্স তৈরি করা হয় | সরাসরি অবজেক্টের নাম দিয়ে এক্সেস করা যায় |
৪. ক্লাসের মধ্যে কনস্ট্রাক্টর (Constructor) ব্যবহার
স্কালায়, কনস্ট্রাক্টর ক্লাসের সাথে যুক্ত থাকে এবং এটি ক্লাসের ইনস্ট্যান্স তৈরি করার সময় ব্যবহৃত হয়। স্কালায় দুটি কনস্ট্রাক্টর থাকে:
- প্রধান কনস্ট্রাক্টর: ক্লাসের সাথে সরাসরি যুক্ত থাকে।
- সহায়ক কনস্ট্রাক্টর: অতিরিক্ত কনস্ট্রাক্টর ফাংশন।
উদাহরণ: কনস্ট্রাক্টর ব্যবহার
class Person(val name: String, val age: Int) {
println(s"Person created: $name, $age")
}
val person1 = new Person("Alice", 30)এখানে:
Personক্লাসে দুটি প্যারামিটারnameএবংageরয়েছে, যেগুলি প্রধান কনস্ট্রাক্টর হিসেবে ব্যবহৃত হচ্ছে।- যখন
new Person("Alice", 30)কল করা হয়, তখনnameএবংageপ্যারামিটার দিয়ে কনস্ট্রাক্টর ইনিশিয়ালাইজ করা হয়।
৫. বিভিন্ন অবজেক্টের মধ্যে এক্সেস
স্কালায়, আপনি একটি অবজেক্টের মধ্যে ডিফাইন করা মেথড এবং ভ্যারিয়েবল অন্য অবজেক্ট থেকে এক্সেস করতে পারেন। একে সিঙ্গেলটন প্যাটার্ন বলা হয়।
উদাহরণ: অবজেক্টের মধ্যে এক্সেস
object Singleton {
val message = "Hello from Singleton"
def greet(): Unit = {
println(message)
}
}
object MainApp {
def main(args: Array[String]): Unit = {
Singleton.greet() // Accessing method from Singleton object
}
}এখানে:
Singletonঅবজেক্টেgreet()মেথড এবং একটি ভ্যারিয়েবলmessageরয়েছে।MainAppঅবজেক্ট থেকেSingleton.greet()মেথড এক্সেস করা হচ্ছে।
৬. অবজেক্ট এবং ক্লাসের মধ্যে মিশ্রণ
স্কালায় আপনি একে অপরের সাথে ক্লাস এবং অবজেক্ট ব্যবহার করতে পারেন। কখনো কখনো, একটি ক্লাস এবং একটি অবজেক্ট একসাথে একটি কার্যকরী কাঠামো তৈরি করতে ব্যবহৃত হয়।
উদাহরণ: ক্লাস এবং অবজেক্টের মিশ্রণ
class Car(val make: String, val model: String) {
def displayDetails(): Unit = {
println(s"Car make: $make, model: $model")
}
}
object CarFactory {
def createCar(make: String, model: String): Car = {
new Car(make, model)
}
}
object MainApp {
def main(args: Array[String]): Unit = {
val car = CarFactory.createCar("Toyota", "Corolla")
car.displayDetails() // Output: Car make: Toyota, model: Corolla
}
}এখানে:
Carএকটি ক্লাস যা গাড়ির তথ্য সংরক্ষণ করে।CarFactoryএকটি অবজেক্ট যাCarক্লাসের ইনস্ট্যান্স তৈরি করে।MainAppঅবজেক্ট থেকে ফ্যাক্টরি মেথডCarFactory.createCarকল করে গাড়ির বিস্তারিত দেখানো হচ্ছে।
সারাংশ
- ক্লাস (Class): স্কালায় ক্লাস হল একটি টেমপ্লেট বা ব্লুপ্রিন্ট, যা অবজেক্ট তৈরি করতে ব্যবহৃত হয়। ক্লাসের মাধ্যমে আপনি একটি অবজেক্টের বিভিন্ন বৈশিষ্ট্য এবং আচরণ ডিফাইন করতে পারেন।
- অবজেক্ট (Object): স্কালায় অবজেক্ট একটি একক ইনস্ট্যান্স থাকে এবং এটি সাধারণত ফাংশনাল প্রোগ্রামিংয়ে ব্যবহৃত হয়। এটি একটি singleton অবজেক্ট, যার একাধিক ইনস্ট্যান্স থাকে না।
স্কালায় ক্লাস এবং অবজেক্ট ব্যবহারের মাধ্যমে আপনি শক্তিশালী এবং স্কেলেবল প্রোগ্রাম তৈরি করতে পারেন।
স্কালায় কনস্ট্রাক্টর এবং ওভারলোডিং দুটি অত্যন্ত গুরুত্বপূর্ণ ধারণা, যা প্রোগ্রামিংয়ের ক্ষেত্রে ক্লাসের ভেতরে বিভিন্ন ধরনের ইনস্ট্যান্স তৈরি এবং মেথডের একাধিক সংস্করণ তৈরি করতে সহায়তা করে। এখানে স্কালার কনস্ট্রাক্টর এবং ওভারলোডিং সম্পর্কে বিস্তারিত আলোচনা করা হলো।
১. কনস্ট্রাক্টর (Constructor)
স্কালায় কনস্ট্রাক্টর একটি বিশেষ মেথড যা ক্লাসের নতুন ইনস্ট্যান্স তৈরি করতে ব্যবহৃত হয়। এটি ক্লাসের একটি অংশ হিসেবে স্বয়ংক্রিয়ভাবে কল হয় যখন নতুন অবজেক্ট তৈরি করা হয়। স্কালায় দুটি ধরনের কনস্ট্রাক্টর থাকে:
- প্রধান কনস্ট্রাক্টর: যেটি ক্লাসের সাথেই ডিফাইন করা হয় এবং ক্লাসের মূল কনস্ট্রাক্টর হিসেবে কাজ করে।
- সহায়ক কনস্ট্রাক্টর: যেটি ক্লাসের ভিতরে অতিরিক্ত কনস্ট্রাক্টর হিসেবে ব্যবহৃত হয়।
১.১ প্রধান কনস্ট্রাক্টর (Primary Constructor)
স্কালায়, প্রধান কনস্ট্রাক্টর সাধারণত ক্লাসের ডেফিনিশনের মধ্যে ডিফাইন করা হয়। এটি একাধিক আর্গুমেন্ট নিতে পারে এবং এই আর্গুমেন্টগুলির মাধ্যমে অবজেক্ট তৈরি করা হয়।
উদাহরণ:
class Person(val name: String, val age: Int) {
// Here, the primary constructor is the part of the class definition.
def greet(): Unit = {
println(s"Hello, my name is $name and I am $age years old.")
}
}
// Creating an object using the primary constructor
val person = new Person("Alice", 30)
person.greet() // Output: Hello, my name is Alice and I am 30 years old.এখানে name এবং age কনস্ট্রাক্টরের মাধ্যমে ইনপুট নেওয়া হচ্ছে এবং greet() মেথডটি এই ভ্যালুগুলিকে ব্যবহার করছে।
১.২ সহায়ক কনস্ট্রাক্টর (Auxiliary Constructor)
স্কালায় সহায়ক কনস্ট্রাক্টর ফাংশনটি মূল কনস্ট্রাক্টরের বাইরে অতিরিক্ত ইনস্ট্যান্স তৈরি করার জন্য ব্যবহৃত হয়। এটি this কিওয়ার্ড দিয়ে ডিফাইন করা হয়।
উদাহরণ:
class Person(val name: String, val age: Int) {
// Primary constructor
def this(name: String) = {
this(name, 18) // Calls the primary constructor with a default age of 18
}
def greet(): Unit = {
println(s"Hello, my name is $name and I am $age years old.")
}
}
// Creating an object using the auxiliary constructor
val person1 = new Person("Bob", 25)
person1.greet() // Output: Hello, my name is Bob and I am 25 years old.
val person2 = new Person("Charlie") // Default age will be 18
person2.greet() // Output: Hello, my name is Charlie and I am 18 years old.এখানে, সহায়ক কনস্ট্রাক্টর name আর্গুমেন্ট গ্রহণ করে এবং age জন্য একটি ডিফল্ট মান (১৮) অ্যাসাইন করে।
২. ওভারলোডিং (Overloading)
ওভারলোডিং হল একাধিক মেথড বা কনস্ট্রাক্টরের একই নাম দিয়ে ভিন্ন ভিন্ন প্যারামিটার সিগনেচার (সংখ্যা বা টাইপ) ব্যবহার করা। এটি স্কালায় সাধারণভাবে মেথড ওভারলোডিং এবং কনস্ট্রাক্টর ওভারলোডিং হিসাবে দেখা যায়।
২.১ মেথড ওভারলোডিং (Method Overloading)
মেথড ওভারলোডিং হল এক বা একাধিক মেথডের একটি নামের মধ্যে ভিন্ন ভিন্ন প্যারামিটার সিগনেচার ব্যবহার করা। একই নামের মেথডের বিভিন্ন সংস্করণ একই ক্লাসের মধ্যে থাকতে পারে, তবে তাদের আর্গুমেন্টসের সংখ্যা বা টাইপ আলাদা হতে হবে।
উদাহরণ:
class Calculator {
def add(a: Int, b: Int): Int = {
a + b
}
def add(a: Double, b: Double): Double = {
a + b
}
}
val calc = new Calculator
println(calc.add(5, 10)) // Output: 15 (Int addition)
println(calc.add(5.5, 10.2)) // Output: 15.7 (Double addition)এখানে, add মেথডটি দুটি আলাদা টাইপের প্যারামিটার গ্রহণ করছে: একবার Int এবং অন্যবার Double। তাই এটি মেথড ওভারলোডিং।
২.২ কনস্ট্রাক্টর ওভারলোডিং (Constructor Overloading)
স্কালায় কনস্ট্রাক্টর ওভারলোডিং হল একাধিক কনস্ট্রাক্টর দিয়ে এক বা একাধিক ক্লাসের ইনস্ট্যান্স তৈরি করা, যেখানে কনস্ট্রাক্টরগুলির প্যারামিটার সিগনেচার আলাদা থাকতে পারে।
উদাহরণ:
class Rectangle(val length: Double, val width: Double) {
// Primary constructor
def this(length: Double) = {
this(length, length) // Creating a square if only one side is provided
}
def area(): Double = length * width
}
val rectangle1 = new Rectangle(5, 10)
println(rectangle1.area()) // Output: 50
val square = new Rectangle(4)
println(square.area()) // Output: 16 (Square case, both sides equal)এখানে, দ্বিতীয় কনস্ট্রাক্টর কেবল একটি মাত্র আর্গুমেন্ট গ্রহণ করে এবং যদি শুধুমাত্র একটি আর্গুমেন্ট প্রদান করা হয় তবে কনস্ট্রাক্টরটি একটি স্কোয়ার তৈরি করবে যেখানে দৈর্ঘ্য এবং প্রস্থ সমান।
সারাংশ
- কনস্ট্রাক্টর: ক্লাসের ইনস্ট্যান্স তৈরি করার জন্য ব্যবহৃত হয়। স্কালায় প্রধান কনস্ট্রাক্টর (primary constructor) এবং সহায়ক কনস্ট্রাক্টর (auxiliary constructor) দুটো ধরনের কনস্ট্রাক্টর রয়েছে।
- ওভারলোডিং: স্কালায় মেথড বা কনস্ট্রাক্টরের নাম একই রাখা যায়, তবে তাদের প্যারামিটার সংখ্যা বা টাইপ ভিন্ন থাকতে হবে। এটি মেথড ও কনস্ট্রাক্টর উভয় ক্ষেত্রেই ব্যবহার করা যায়।
কনস্ট্রাক্টর ও ওভারলোডিং স্কালা প্রোগ্রামিংয়ের শক্তিশালী ফিচার, যা কোডের পুনঃব্যবহারযোগ্যতা এবং কার্যকারিতা বাড়ায়।
স্কালা প্রোগ্রামিং ভাষায় ইনহেরিটেন্স (Inheritance) এবং পলিমরফিজম (Polymorphism) হল অবজেক্ট-অরিয়েন্টেড প্রোগ্রামিংয়ের দুটি গুরুত্বপূর্ণ ধারণা। এই দুটি বৈশিষ্ট্য কোডের পুনঃব্যবহারযোগ্যতা এবং নমনীয়তা (flexibility) বৃদ্ধি করে।
১. ইনহেরিটেন্স (Inheritance)
ইনহেরিটেন্স হল একটি প্রক্রিয়া যার মাধ্যমে একটি ক্লাস অন্য একটি ক্লাস থেকে বৈশিষ্ট্য (ফিল্ড, মেথড) এবং আচরণ (behaviors) উত্তরাধিকার (inherit) করে। এটি কোড পুনঃব্যবহার এবং সহজেই নতুন বৈশিষ্ট্য সংযোজনের জন্য ব্যবহৃত হয়।
স্কালায়, ক্লাস ইনহেরিট করতে extends কিওয়ার্ড ব্যবহার করা হয়। এটি একটি ক্লাসকে অন্য ক্লাস থেকে উত্তরাধিকার (inherit) করার অনুমতি দেয়।
১.১ ইনহেরিটেন্স উদাহরণ
// Superclass (Parent class)
class Animal {
def speak(): Unit = {
println("The animal makes a sound")
}
}
// Subclass (Child class) inherits from Animal
class Dog extends Animal {
def speak(): Unit = {
println("The dog barks")
}
}
// Main object to test inheritance
object InheritanceExample {
def main(args: Array[String]): Unit = {
val dog = new Dog()
dog.speak() // Output: The dog barks
val animal = new Animal()
animal.speak() // Output: The animal makes a sound
}
}এখানে:
Dogক্লাসAnimalক্লাস থেকে ইনহেরিট করেছে, কিন্তু এটিspeak()মেথডটি ওভাররাইড (override) করেছে যাতে ডগের জন্য নির্দিষ্ট আচরণ (বাক) তৈরি করা যায়।Dogক্লাসAnimalক্লাসের বৈশিষ্ট্যগুলো উত্তরাধিকার হিসেবে পেয়ে থাকে, তবেDogক্লাস তার নিজস্ব আচরণ প্রদান করতে পারে।
২. পলিমরফিজম (Polymorphism)
পলিমরফিজম হল একটি ধারণা যার মাধ্যমে একে একাধিক উপায়ে ব্যবহার করা যায়। এটি এক বা একাধিক মেথড বা অপারেশনকে বিভিন্ন ধরনের অবজেক্টের জন্য বিভিন্ন উপায়ে ব্যবহার করতে দেয়।
পলিমরফিজম দুটি ধরনের হতে পারে:
- মেথড পলিমরফিজম (Method Polymorphism): একই নামের মেথডের বিভিন্ন বাস্তবায়ন (implementation) থাকতে পারে।
- অপারেটর পলিমরফিজম (Operator Polymorphism): একই অপারেটরের জন্য বিভিন্ন আর্গুমেন্টের সাথে কাজ করার ক্ষমতা।
২.১ মেথড পলিমরফিজম (Method Polymorphism)
মেথড পলিমরফিজম হল একই মেথড নামের একাধিক ভার্সন থাকা, যা বিভিন্ন আর্গুমেন্ট গ্রহণ করে বা প্যারামিটার অনুসারে বিভিন্ন আচরণ প্রদর্শন করে।
// Superclass (Parent class)
class Animal {
def speak(): Unit = {
println("The animal makes a sound")
}
}
// Subclass (Child class) inherits from Animal
class Dog extends Animal {
override def speak(): Unit = {
println("The dog barks")
}
}
// Another subclass (Child class)
class Cat extends Animal {
override def speak(): Unit = {
println("The cat meows")
}
}
// Main object to test polymorphism
object PolymorphismExample {
def main(args: Array[String]): Unit = {
val dog: Animal = new Dog() // Dog object as Animal type
val cat: Animal = new Cat() // Cat object as Animal type
dog.speak() // Output: The dog barks
cat.speak() // Output: The cat meows
}
}এখানে:
DogএবংCatক্লাস দুটিspeak()মেথডটি ওভাররাইড (override) করেছে।DogএবংCatঅবজেক্টগুলিAnimalটাইপের হয়ে থাকা সত্ত্বেও, তারা তাদের নিজস্ব আচরণ প্রদর্শন করে।
২.২ অপারেটর পলিমরফিজম (Operator Polymorphism)
স্কালায় অপারেটর পলিমরফিজমের মাধ্যমে একই অপারেটরের বিভিন্ন প্রকার ব্যবহার করা যায়। এটি সাধারণত কাস্টম অপারেটর ডিফাইন করার জন্য ব্যবহৃত হয়।
class Complex(val real: Double, val imaginary: Double) {
def +(that: Complex): Complex = {
new Complex(this.real + that.real, this.imaginary + that.imaginary)
}
def display(): Unit = {
println(s"${real} + ${imaginary}i")
}
}
object OperatorPolymorphismExample {
def main(args: Array[String]): Unit = {
val complex1 = new Complex(3.0, 4.0)
val complex2 = new Complex(1.0, 2.0)
val result = complex1 + complex2 // Using the overloaded + operator
result.display() // Output: 4.0 + 6.0i
}
}এখানে:
+অপারেটরকে কাস্টমাইজ করা হয়েছে যাতে এটি দুটিComplexঅবজেক্টকে যোগ করতে পারে।
৩. এবস্ট্রাকশন (Abstraction) এবং ইনহেরিটেন্স
এবস্ট্রাকশন এবং ইনহেরিটেন্স একে অপরের সাথে সম্পর্কিত। স্কালায় abstract class এবং trait এর মাধ্যমে আপনি অবজেক্ট-অরিয়েন্টেড প্রোগ্রামিংয়ের এবস্ট্রাকশন ব্যবহার করতে পারেন।
৩.১ এবস্ট্রাক্ট ক্লাস (Abstract Class)
abstract class Animal {
def sound(): Unit // Abstract method without implementation
}
class Dog extends Animal {
def sound(): Unit = {
println("Bark")
}
}
object AbstractClassExample {
def main(args: Array[String]): Unit = {
val dog = new Dog()
dog.sound() // Output: Bark
}
}এখানে:
Animalক্লাস একটিabstractক্লাস, যেখানেsound()মেথডটি অ্যাবস্ট্রাক্ট (অমীমাংসিত) হিসেবে ডিফাইন করা হয়েছে।Dogক্লাসেsound()মেথডের বাস্তবায়ন (implementation) দেওয়া হয়েছে।
সারাংশ
- ইনহেরিটেন্স হল একটি ক্লাসের বৈশিষ্ট্য এবং আচরণ অন্য ক্লাস দ্বারা উত্তরাধিকার (inherit) করার প্রক্রিয়া।
- পলিমরফিজম হল একই নামের মেথডের বিভিন্ন বাস্তবায়ন (overloading বা overriding) বা অপারেটরের বিভিন্ন ব্যবহারের ক্ষমতা।
এগুলি স্কালায় কোডের পুনঃব্যবহারযোগ্যতা, নমনীয়তা এবং কার্যকারিতা বাড়াতে সহায়ক।
ট্রেইট (Trait) এবং মিক্সইন (Mixin) স্কালার দুটি গুরুত্বপূর্ণ বৈশিষ্ট্য, যা অবজেক্ট-অরিয়েন্টেড প্রোগ্রামিং (OOP) এবং ফাংশনাল প্রোগ্রামিং (FP) এর মধ্যে একটি শক্তিশালী সমন্বয় তৈরি করতে ব্যবহৃত হয়। স্কালায় ট্রেইট এবং মিক্সইন ব্যবহারের মাধ্যমে কোডের পুনঃব্যবহারযোগ্যতা এবং নমনীয়তা বাড়ানো যায়।
১. ট্রেইট (Traits)
ট্রেইট হল এমন একটি ধরনের ক্লাস যা একাধিক ক্লাসের মধ্যে পুনঃব্যবহারযোগ্য কোড শেয়ার করার জন্য ব্যবহৃত হয়। ট্রেইটের মধ্যে আপনি ফাংশন এবং ভ্যারিয়েবল ডিফাইন করতে পারেন, এবং ট্রেইটগুলোকে মিশ্রিত (mix) করতে পারেন বিভিন্ন ক্লাসের মধ্যে।
ট্রেইটগুলো মূলত এক ধরনের ইন্টারফেস-এর মতো কাজ করে, কিন্তু এগুলো ক্লাসের মতো কিছু ফাংশনালিটি এবং বাস্তবায়নও সরবরাহ করতে পারে।
ট্রেইট তৈরি করা
trait Animal {
def sound: String // Abstract method
def move(): Unit = { // Concrete method
println("Moving around...")
}
}
class Dog extends Animal {
def sound: String = "Woof"
}
class Cat extends Animal {
def sound: String = "Meow"
}
object Main extends App {
val dog = new Dog
val cat = new Cat
println(dog.sound) // Output: Woof
dog.move() // Output: Moving around...
println(cat.sound) // Output: Meow
cat.move() // Output: Moving around...
}এখানে:
trait Animal: এটি একটি ট্রেইট যার মধ্যে একটি abstract methodsoundএবং একটি concrete methodmoveআছে।DogএবংCatক্লাস: এই দুটি ক্লাসAnimalট্রেইট থেকে inherit করে এবংsoundমেথডটি বাস্তবায়ন করে।
ট্রেইট এর সুবিধা:
- ক্লাসের মধ্যে কোড পুনঃব্যবহার: ট্রেইট কোডের পুনঃব্যবহারযোগ্য অংশ হিসেবে কাজ করে, যাতে আপনি একাধিক ক্লাসে কমন ফাংশনালিটি শেয়ার করতে পারেন।
- ফাংশনাল এবং অবজেক্ট-অরিয়েন্টেড প্রোগ্রামিংয়ের সমন্বয়: স্কালায় ট্রেইট ফাংশনাল এবং অবজেক্ট-অরিয়েন্টেড প্রোগ্রামিংয়ের শক্তিশালী সমন্বয় ঘটায়।
২. মিক্সইন (Mixins)
মিক্সইন হলো একটি স্কালা ফিচার, যার মাধ্যমে একটি ক্লাস বা অবজেক্ট একাধিক ট্রেইটের মধ্যে ফাংশনালিটি শেয়ার করতে পারে। মিক্সইন এইভাবে কোডের পুনঃব্যবহারযোগ্যতা বৃদ্ধি করে, কারণ একাধিক ট্রেইট একসাথে মিশ্রিত করা যায় এবং বিভিন্ন ক্লাসে প্রয়োগ করা যায়।
স্কালায় মিক্সইন করার জন্য with কিওয়ার্ড ব্যবহার করা হয়।
মিক্সইন উদাহরণ
trait Animal {
def sound: String
}
trait Movable {
def move(): Unit = println("Moving around...")
}
class Dog extends Animal with Movable {
def sound: String = "Woof"
}
class Cat extends Animal with Movable {
def sound: String = "Meow"
}
object Main extends App {
val dog = new Dog
println(dog.sound) // Output: Woof
dog.move() // Output: Moving around...
val cat = new Cat
println(cat.sound) // Output: Meow
cat.move() // Output: Moving around...
}এখানে:
Movableট্রেইটটিDogএবংCatক্লাসের সাথে মিক্সইন করা হয়েছে, যাতে এই দুটি ক্লাসmoveমেথডটি ব্যবহার করতে পারে।withকিওয়ার্ড ব্যবহার করেDogএবংCatক্লাসে ট্রেইটগুলো মিক্স করা হয়েছে।
মিক্সইন এর সুবিধা:
- বহু ট্রেইট মিশ্রণ: আপনি একাধিক ট্রেইট একসাথে মিক্স করতে পারেন, যা কোডের পুনঃব্যবহারযোগ্যতা এবং নমনীয়তা বাড়ায়।
- প্রতিটি ক্লাসে আলাদা ফাংশনালিটি: মিক্সইন ব্যবহারের মাধ্যমে ক্লাসগুলোতে আলাদা আলাদা ফাংশনালিটি মিশ্রিত করা যায়, যা কোডের গঠন আরও ভালো করে।
৩. ট্রেইট এবং মিক্সইনের পার্থক্য
| বৈশিষ্ট্য | ট্রেইট (Trait) | মিক্সইন (Mixin) |
|---|---|---|
| সংজ্ঞায়ন | একাধিক ক্লাসের মধ্যে কোড শেয়ার করার জন্য ট্রেইট ব্যবহার করা হয়। | মিক্সইন, একাধিক ট্রেইট একসাথে একটি ক্লাসে শেয়ার করা হয়। |
| ফাংশনালিটি | ট্রেইট নিজেই কিছু ফাংশনালিটি বা abstract মেথড প্রদান করে। | মিক্সইন হলো একাধিক ট্রেইটের ফাংশনালিটির মিশ্রণ। |
| ব্যবহার | ট্রেইট ক্লাস বা অবজেক্টে ব্যবহৃত হয় এবং সেই ক্লাসে কোড পুনঃব্যবহারযোগ্য করতে সাহায্য করে। | মিক্সইন একাধিক ট্রেইটকে একত্রে ব্যবহার করার জন্য ব্যবহৃত হয়। |
৪. একাধিক ট্রেইট মিশ্রণ (Multiple Trait Mixing)
স্কালায় আপনি একাধিক ট্রেইট একসাথে মিশ্রিত করতে পারেন। যদি বিভিন্ন ট্রেইটের মধ্যে কিছু সাধারণ ফাংশন বা প্রোপার্টি থাকে, তবে এগুলি মিশ্রিত করে আরও শক্তিশালী ফাংশনালিটি তৈরি করা যায়।
উদাহরণ:
trait Animal {
def sound: String
}
trait Movable {
def move(): Unit = println("Moving around...")
}
trait Swimmable {
def swim(): Unit = println("Swimming...")
}
class Dog extends Animal with Movable {
def sound: String = "Woof"
}
class Fish extends Animal with Swimmable {
def sound: String = "Blub"
}
object Main extends App {
val dog = new Dog
dog.move() // Output: Moving around...
val fish = new Fish
fish.swim() // Output: Swimming...
}এখানে:
Dogক্লাসেMovableট্রেইট মিক্সইন করা হয়েছে।Fishক্লাসেSwimmableট্রেইট মিক্সইন করা হয়েছে।
সারাংশ
- ট্রেইট (Trait) হল একটি অবজেক্ট-অরিয়েন্টেড কনসেপ্ট যা কোডের পুনঃব্যবহারযোগ্যতা বাড়ানোর জন্য ব্যবহৃত হয় এবং একাধিক ক্লাসে শেয়ার করা যায়।
- মিক্সইন (Mixin) হল ট্রেইটগুলির সমন্বয়, যেখানে একাধিক ট্রেইট একসাথে কোনো ক্লাসে যুক্ত করা হয়।
- স্কালায় ট্রেইট এবং মিক্সইন ব্যবহারের মাধ্যমে কোডের পুনঃব্যবহারযোগ্যতা, নমনীয়তা, এবং কার্যকারিতা বৃদ্ধি পায়।
এ দুটি বৈশিষ্ট্য স্কালার কোডকে আরও পরিষ্কার, শক্তিশালী এবং পুনঃব্যবহারযোগ্য করে তোলে।
অ্যাবস্ট্রাক্ট ক্লাস এবং ফাইনাল কিওয়ার্ড স্কালা প্রোগ্রামিং ভাষার গুরুত্বপূর্ণ বৈশিষ্ট্য। এগুলি ক্লাসের বিশেষ বৈশিষ্ট্য এবং ইনহেরিটেন্স (Inheritance) সম্পর্কিত বিভিন্ন কনসেপ্টের সঙ্গে সম্পর্কিত। এখানে স্কালার অ্যাবস্ট্রাক্ট ক্লাস এবং ফাইনাল কিওয়ার্ডের ব্যবহার এবং উদাহরণ আলোচনা করা হলো।
১. অ্যাবস্ট্রাক্ট ক্লাস (Abstract Class)
অ্যাবস্ট্রাক্ট ক্লাস এমন একটি ক্লাস যা সম্পূর্ণভাবে বাস্তবায়িত (implemented) না হয়ে কিছু অংশ অনির্দিষ্ট (abstract) রেখে দেয়, এবং এই ক্লাসটি সরাসরি ইনস্ট্যান্স (instance) তৈরি করা যায় না। অ্যাবস্ট্রাক্ট ক্লাসকে অন্য ক্লাস দ্বারা সম্প্রসারিত (extend) করা হয় এবং সেখানে এর অনির্দিষ্ট মেথডগুলির বাস্তবায়ন প্রদান করা হয়।
অ্যাবস্ট্রাক্ট ক্লাস ডিফাইন করা:
// অ্যাবস্ট্রাক্ট ক্লাস
abstract class Animal {
// একটি abstract মেথড (এটি কোন কোড রিটার্ন করে না)
def sound(): String
// একটি সাধারণ মেথড
def sleep(): String = {
"Sleeping..."
}
}
// অ্যাবস্ট্রাক্ট ক্লাস ইনহেরিট করে বাস্তব ক্লাস
class Dog extends Animal {
// abstract মেথডের বাস্তবায়ন
def sound(): String = {
"Bark"
}
}
object AbstractClassExample {
def main(args: Array[String]): Unit = {
val dog = new Dog()
println(dog.sound()) // Output: Bark
println(dog.sleep()) // Output: Sleeping...
}
}এখানে:
- abstract class:
Animalএকটি অ্যাবস্ট্রাক্ট ক্লাস, যার মধ্যে একটিabstractমেথডsound()রয়েছে। - abstract method:
sound()মেথডের কোনও বাস্তবায়ন নেই, এটি কেবল ক্লাসের উপরে ডিফাইন করা হয়েছে। - real class:
Dogক্লাসAnimalক্লাসের উপরে ইনহেরিট করে এবংsound()মেথডের বাস্তবায়ন প্রদান করেছে।
২. ফাইনাল কিওয়ার্ড (Final Keyword)
ফাইনাল কিওয়ার্ড ব্যবহৃত হয় ক্লাস, মেথড বা ভ্যারিয়েবলগুলিতে, যার মাধ্যমে সেই ক্লাস, মেথড বা ভ্যারিয়েবলটি পরিবর্তন বা ইনহেরিট করা যাবে না।
২.১ ফাইনাল ক্লাস
যখন একটি ক্লাসে final কিওয়ার্ড ব্যবহার করা হয়, তখন সে ক্লাসটি অন্য কোন ক্লাস দ্বারা ইনহেরিট (extend) করা যাবে না। অর্থাৎ, সেই ক্লাসটি ফাইনাল হয়ে যায়।
final class Car {
def start(): Unit = {
println("Car started!")
}
}
// এই কোডটি কম্পাইল হবে না, কারণ Car ক্লাসটি ফাইনাল
// class ElectricCar extends Car { } // Error: Cannot extend final classএখানে:
Carক্লাসেfinalকিওয়ার্ড দেওয়া হয়েছে, ফলে এটি আর কোনো ক্লাস দ্বারা ইনহেরিট করা যাবে না।
২.২ ফাইনাল মেথড
যদি একটি মেথডে final কিওয়ার্ড ব্যবহার করা হয়, তাহলে সেই মেথডটি ওভাররাইড (override) করা যাবে না।
class Vehicle {
final def move(): Unit = {
println("Vehicle is moving")
}
}
class Car extends Vehicle {
// এই কোডটি কম্পাইল হবে না, কারণ move() মেথডটি ফাইনাল
// override def move(): Unit = {
// println("Car is moving")
// }
}এখানে:
move()মেথডেfinalকিওয়ার্ড ব্যবহৃত হয়েছে, যার কারণে এটি override করা যাবে না।
২.৩ ফাইনাল ভ্যারিয়েবল
ফাইনাল ভ্যারিয়েবল এমন একটি ভ্যারিয়েবল, যার মান একবার অ্যাসাইন করার পর তা আর পরিবর্তন করা যায় না।
object FinalVariableExample {
final val maxSpeed = 120
def main(args: Array[String]): Unit = {
// maxSpeed = 130 // Error: reassignment to val
println(s"Max Speed: $maxSpeed")
}
}এখানে:
maxSpeedএকটি ফাইনাল ভ্যারিয়েবল, যার মান একবার নির্ধারণ করার পর তা আর পরিবর্তন করা যাবে না।
সারাংশ
- অ্যাবস্ট্রাক্ট ক্লাস: এটি এমন একটি ক্লাস যা সম্পূর্ণভাবে বাস্তবায়িত না হয়ে কিছু অংশ অনির্দিষ্ট রেখে দেয় এবং এটি সরাসরি ইনস্ট্যান্স তৈরি করতে পারে না। এটি ইনহেরিট করে অন্যান্য ক্লাসে তার অনির্দিষ্ট অংশগুলোর বাস্তবায়ন করা হয়।
- ফাইনাল কিওয়ার্ড:
- ফাইনাল ক্লাস: এটি এমন একটি ক্লাস যা অন্য কোন ক্লাস দ্বারা ইনহেরিট করা যাবে না।
- ফাইনাল মেথড: এটি এমন একটি মেথড যা ওভাররাইড করা যাবে না।
- ফাইনাল ভ্যারিয়েবল: এটি এমন একটি ভ্যারিয়েবল যার মান একবার অ্যাসাইন করার পর তা আর পরিবর্তন করা যায় না।
এগুলি স্কালার ইনহেরিটেন্স, ক্লাস, এবং অবজেক্ট মডেলিংয়ে গুরুত্বপূর্ণ ভূমিকা পালন করে এবং কোডকে আরো সুরক্ষিত ও কার্যকরী করে তোলে।
Read more