কনস্ট্রাকটর:

কন্সট্রাক্টর হল ক্লাসের একটি মেথড । যখন আমরা কোন একটি ক্লাসের অবজেক্ট তৈরি করতে যাই তখন ক্লাসের কন্সট্রাক্টর মেথড কল হয়ে এবং অব্জেক্টিকে তৈরি করে দেয় । কন্সট্রাক্টরের নাম এবং ক্লাস এর নাম একই থাকে ।

ডিফল্ট কন্সট্রাক্টরঃ

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

class Car {
String manufacturerCompany = 'BMW';
String color = 'Black';
int numberOfSeats = 4;

// Default Constructor
Car();
}

void main() {
Car car = Car();
print(car.manufacturerCompany);
print(car.color);
print(car.numberOfSeats);
}
 

কন্সট্রাক্টর উইথ প্যারামিটারসঃ

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

class Car {
String manufacturerCompany;
String color;
int numberOfSeats;

Car(
this.manufacturerCompany,
this.color,
this.numberOfSeats,
);
}

void main() {
Car car = Car('Toyota', 'Green', 4);
print(car.manufacturerCompany);
print(car.color);
print(car.numberOfSeats);
}
 

আউটপুট:

Toyota
Green
4
 

আমরা জানি যে ডার্ট ল্যাঙ্গুয়েজ নেমড প্যারামিটার এর সুবিধা দিয়ে থাকে । আমরা এখন আমাদের কন্সট্রাক্টর এ পাস করা প্যারামিটার গুলোকে নেমড প্যারামিটার দিয়ে ইমপ্লিমেন্ট করে দেখব

class Car {
String manufacturerCompany;
String color;
int numberOfSeats;

Car({
required this.manufacturerCompany,
required this.color,
required this.numberOfSeats,
});
}

void main() {
Car car = Car(
manufacturerCompany: 'Toyota',
color: 'Green',
numberOfSeats: 4,
);
print(car.manufacturerCompany);
print(car.color);
print(car.numberOfSeats);
}
 

আউটপুট :

Toyota
Green
4
 

নেমড প্যারামিটার ব্যাবহার করার কিছু সুবিধা হল, যেমন : প্যারামিটার গুলো কি কাজ করতেছে সেটার একটা ভালো ব্যাখ্যা পাওয়া যায় এবং প্যারামিটার গুলোর সিরিয়ালটিকে মনে রাখার প্রয়োজন পরে না।

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

class Car {
String manufacturerCompany;
String color;
int numberOfSeats;

Car({
required this.manufacturerCompany,
required this.color,
this.numberOfSeats = 4,
});
}

void main() {
Car car = Car(
manufacturerCompany: 'Toyota',
color: 'Green',
);
print(car.manufacturerCompany);
print(car.color);
print(car.numberOfSeats);
}
 

আউটপুট :

Toyota
Green
4
 

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

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

class Car {
String manufacturerCompany;
String color;
int numberOfSeats;

Car(
this.manufacturerCompany, [
this.color = 'Green',
this.numberOfSeats = 4,
]);
}

void main() {
Car car = Car(
'Toyota',
);
print(car.manufacturerCompany);
print(car.color);
print(car.numberOfSeats);
}
 

আউটপুট :

Toyota
Green
4
 

নেমড কন্সট্রাক্টরঃ

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

class Car {
String manufacturerCompany;
String color;
int numberOfSeats;

Car(
this.manufacturerCompany, [
this.color = 'Black',
this.numberOfSeats = 4,
]);

Car.madeByBmw({
this.manufacturerCompany = 'BMW',
required this.color,
required this.numberOfSeats,
});

Car.madeByToyota({
this.manufacturerCompany = 'Toyota',
required this.color,
required this.numberOfSeats,
});
}

void main() {
Car bmwCar = Car.madeByBmw(
color: 'Black',
numberOfSeats: 4,
);

Car toyotaCar = Car.madeByToyota(
color: 'Green',
numberOfSeats: 6,
);

print(bmwCar.manufacturerCompany);
print(bmwCar.color);
print(bmwCar.numberOfSeats);

print(toyotaCar.manufacturerCompany);
print(toyotaCar.color);
print(toyotaCar.numberOfSeats);

}
 

আউটপুট:

BMW
Black
4
Toyota
Green
6
 

এখানে প্রথম নেমড কন্সট্রাক্টর দিয়ে BMW টাইপের এবং দ্বিতীয় নেমড কন্সট্রাক্টর দিয়ে Toyota টাইপের গাড়ির অবজেক্ট তৈরি করা হয়েছে ।

প্রাইভেট কন্সট্রাক্টরঃ

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

class PrivateConstructor {
PrivateConstructor._internal();
}

void main(){
PrivateConstructor privateConstructor = PrivateConstructor();
}
 

এভাবে করে PrivateConstructor ক্লাসের কোন অবজেক্ট ডার্ট তৈরি করতে দিবেনা কারণ PrivateConstructor ক্লাসের কোন পাবলিক কন্সট্রাক্টর ডিফাইন করে দেওয়া নাই । এই কোডটি লেখার পরে একটি কম্পাইলার এরর শো করবে ।

কন্সটান্ট কন্সট্রাক্টরঃ

ডার্ট আমাদেরকে কন্সটান্ট কন্সট্রাক্টর তৈরি করে দেওয়ার সুবিধা দেয় । এটার মানে কি দাঁড়ালো ? আমরা যদি এমন একটা ক্লাস ডিজাইন করি যার কোন অবজেক্ট একবার তৈরি হওয়ার পরে আর বদলানর কোন সুযোগ নাই তাহলে আমরা সেই ক্লাসটির কন্সট্রাক্টরকে কন্সটান্ট কন্সট্রাক্টর হিসিবে ডিফাইন করে দিতে পারি । তবে মনে রাখতে হবে এই ক্ষেত্রে ক্লাসের সব ভেরিয়েবল গুলোকে হতে হবে ফাইনাল ভেরিয়েবল।

class BlackFourSeaterCarMadeByBMW {
final String manufacturerCompany;
final String color;
final int numberOfSeats;

const BlackFourSeaterCarMadeByBMW(
this.manufacturerCompany,
this.color,
this.numberOfSeats,
);
}
 

ফ্যাক্টরি কন্সট্রাক্টরঃ

ডার্টে ফ্যাক্টরি কন্সট্রাক্টর ব্যাবহার করতে পারা যায় । তবে ফ্যাক্টরি কন্সট্রাক্টর কি? কেন এবং কোথায় ব্যাবহার করা হয় সেটি নিয়ে আমরা আবার আলোচনা করব এই অধ্যায়ের শেষে। ডার্ট ল্যাঙ্গুয়েজ এর কন্সট্রাক্টর নিয়ে আলোচনার এখানেই আপাতত ইতি ।

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

class DatabaseConnection {
final String _url;

// Private constructor to create a database connection
DatabaseConnection._(this._url);

// Static map to store and reuse database connections
static final Map _connections = {};

// Factory constructor to get a database connection
factory DatabaseConnection(String url) {
if (_connections.containsKey(url)) {
return _connections[url]!;
} else {
final newConnection = DatabaseConnection._(url);
_connections[url] = newConnection;
return newConnection;
}
}

// Simulate opening a database connection
void open() {
print('Opened database connection to $_url');
}

// Simulate closing a database connection
void close() {
print('Closed database connection to $_url');
}
}

void main() {
final dbConnection1 = DatabaseConnection('example.com/db');
final dbConnection2 = DatabaseConnection('example.com/db');

// Both references should point to the same database connection
print(identical(dbConnection1, dbConnection2)); // true

dbConnection1.open();
dbConnection1.close();
}