Lesson ৮ মিনিট পড়া

ক্লাসেস এবং অবজেক্টস (Classes & Objects)

আপনার নিজের কাস্টম টাইপ তৈরি করুন — যা ব্লুপ্রিন্ট প্যাটার্ন (blueprint pattern) নামে পরিচিত

ক্লাস হলো এক ধরনের ব্লুপ্রিন্ট (Classes Are Blueprints)

যেকোনো ক্লাসকে বাড়ি তৈরির একটি ব্লুপ্রিন্ট (blueprint) বা নকশার মতো ভাবতে পারেন। ব্লুপ্রিন্ট নিজে কিন্তু কোনো বাড়ি নয় — এটি বরং এমন একটি পরিকল্পনা বা প্ল্যান, যা বলে দেয় যে বাড়িটি দেখতে ঠিক কেমন হবে (এর ঘর, দরজা, জানালা ইত্যাদি)। যখন আপনি সেই ব্লুপ্রিন্ট দেখে সত্যিকার অর্থে একটি বাড়ি তৈরি করেন, তখন সেই বাড়িটিকে বলা হয় একটি অবজেক্ট (object) (যাকে "ইনস্ট্যান্স (instance)" বলেও ডাকা হয়)।

আপনি চাইলে একই ব্লুপ্রিন্ট থেকে অনেকগুলো বাড়ি তৈরি করতে পারেন। প্রতিটি বাড়িই সম্পূর্ণ আলাদা — একটি হয়তো লাল রঙের, আরেকটি হয়তো নীল রঙের — কিন্তু ভেতরের গঠন বা স্ট্রাকচার সবার ক্ষেত্রেই একই রকম।

একটি ক্লাস মূলত তিনটি জিনিসকে একসাথে বেঁধে রাখে:

  • ফিল্ডস/প্রোপার্টিজ (Fields/Properties) — ডেটা (অবজেক্টটি নিজের সম্পর্কে কী জানে)
  • মেথডস (Methods) — ব্যবহার বা আচার-আচরণ (অবজেক্টটি কী করতে পারে)
  • কনস্ট্রাক্টর (Constructor) — সেটআপ করার নিয়মকানুন (অবজেক্টটিকে কীভাবে তৈরি করা হবে তার নিয়ম)

আপনার প্রথম ক্লাস (Your First Class)

// The blueprint
class Dog
{
// Properties — what a Dog knows about itself
public string Name { get; set; }
public string Breed { get; set; }
public int Age { get; set; }
// Constructor — how to build a Dog
public Dog(string name, string breed, int age)
{
Name = name;
Breed = breed;
Age = age;
}
// Method — what a Dog can do
public string Bark()
{
return Age < 2 ? "Yip! Yip!" : "Woof! Woof!";
}
public string Introduce()
{
return $"I'm {Name}, a {Age}-year-old {Breed}.";
}
}
// Create objects from the blueprint
var buddy = new Dog("Buddy", "Golden Retriever", 5);
var puppy = new Dog("Tiny", "Chihuahua", 1);
Console.WriteLine(buddy.Introduce());
Console.WriteLine($"Buddy says: {buddy.Bark()}");
Console.WriteLine(puppy.Introduce());
Console.WriteLine($"Tiny says: {puppy.Bark()}");
Output
I'm Buddy, a 5-year-old Golden Retriever.
Buddy says: Woof! Woof!
I'm Tiny, a 1-year-old Chihuahua.
Tiny says: Yip! Yip!

প্রোপার্টিজ — স্মার্ট ফিল্ডস (Properties — Smart Fields)

প্রোপার্টিগুলোকে (Properties) দেখতে সাধারণ ফিল্ডের (fields) মতোই মনে হয়, কিন্তু এদের কিছু জাদুকরী ক্ষমতা রয়েছে। { get; set; } সিনট্যাক্সটি একটি অটো-প্রোপার্টি (auto-property) তৈরি করে — সি শার্প (C#) নিজে থেকেই ব্যাকগ্রাউন্ডে একটি লুকানো বা হিডেন ব্যাকিং ফিল্ড (hidden backing field) তৈরি করে নেয়। তবে আপনি চাইলে নিজের মনের মতো কাস্টম লজিকও (custom logic) লিখতে পারবেন:

  • get — যখন কেউ এর ভেতরের ভ্যালু বা মানটুকু পড়তে চায়, তখন এটি রান করে
  • set — যখন কেউ এর ভেতরে কোনো নতুন ভ্যালু বা মান অ্যাসাইন (assign) করে, তখন এটি রান করে (এতে value কিবোর্ডটি (keyword) ব্যবহার করতে হয়)
  • init — এটি অনেকটা set এর মতোই, তবে এটি কাজ করে কেবল অবজেক্টটি তৈরি হওয়ার ঠিক ওই মুহূর্তেই

তাছাড়া প্রোপার্টিগুলো আপনাকে ভ্যালিডেশন (validation) বা যাচাই-বাছাই করার সুযোগ দেয় — ঠিক যেমন কোনো ক্লাবের দরজায় দাঁড়িয়ে থাকা বাউন্সার (bouncer) সবার আইডি (IDs) চেক করে ভেতরে ঢোকার অনুমতি দেয়।

প্রোপার্টিজ এবং অ্যাক্সেস মডিফায়ার (Properties & Access Modifiers)

class BankAccount
{
public string Owner { get; init; } // set only during creation
private decimal _balance; // private backing field
public decimal Balance
{
get => _balance;
private set // only this class can set it
{
if (value < 0)
throw new ArgumentException("Balance can't be negative!");
_balance = value;
}
}
// Computed property — no backing field needed
public string Status => Balance > 1000 ? "Gold Member" : "Standard";
public BankAccount(string owner, decimal initialDeposit)
{
Owner = owner;
Balance = initialDeposit;
}
public void Deposit(decimal amount)
{
Balance += amount;
Console.WriteLine($"Deposited {amount:C}. New balance: {Balance:C}");
}
public void Withdraw(decimal amount)
{
if (amount > Balance)
{
Console.WriteLine("Insufficient funds!");
return;
}
Balance -= amount;
Console.WriteLine($"Withdrew {amount:C}. New balance: {Balance:C}");
}
}
var account = new BankAccount("Laboni", 500);
Console.WriteLine($"Owner: {account.Owner}, Status: {account.Status}");
account.Deposit(700);
Console.WriteLine($"Status: {account.Status}");
account.Withdraw(200);
account.Withdraw(5000);
Output
Owner: Laboni, Status: Standard
Deposited $700.00. New balance: $1,200.00
Status: Gold Member
Withdrew $200.00. New balance: $1,000.00
Insufficient funds!

স্ট্যাটিক মেম্বারস — সবার সাথে শেয়ার করা (Static Members — Shared Across All Objects)

সাধারণ প্রোপার্টি (properties) এবং মেথডগুলো (methods) শুধু একেকটি আলাদা আলাদা অবজেক্টের নিজস্ব সম্পত্তি হিসেবে কাজ করে। কিন্তু static মেম্বারগুলো হলো ওই ক্লাসটির (class itself) সম্পত্তি — যাকে ওই ক্লাসের তৈরি করা সব অবজেক্ট শেয়ার করে ব্যবহার করতে পারে।

ব্যাপারটিকে এভাবে ভাবতে পারেন: প্রতিটি শিক্ষার্থীর কিন্তু নিজের আলাদা একটি নাম থাকে (যাকে বলা যায় ইনস্ট্যান্স প্রোপার্টি), কিন্তু তারা সবাই মিলে একই স্কুলের নাম শেয়ার করে (যাকে বলা যায় স্ট্যাটিক প্রোপার্টি)। আপনি কোনো অবজেক্টের (object) মাধ্যমে নয়, বরং সরাসরি ওই ক্লাসের নামের মাধ্যমেই স্ট্যাটিক মেম্বারগুলোকে অ্যাক্সেস (access) করতে পারেন।

স্ট্যাটিক মেম্বারস (Static Members)

class Player
{
// Static — shared by ALL players
public static int TotalPlayers { get; private set; } = 0;
// Instance — unique to each player
public string Name { get; set; }
public int Score { get; set; }
public Player(string name)
{
Name = name;
Score = 0;
TotalPlayers++; // every new player increments the count
}
// Static method
public static void ShowPlayerCount()
{
Console.WriteLine($"Total players in the game: {TotalPlayers}");
}
public override string ToString() => $"{Name} (Score: {Score})";
}
var p1 = new Player("Anika");
var p2 = new Player("Rafi");
var p3 = new Player("Sadia");
p1.Score = 100;
p2.Score = 85;
Console.WriteLine(p1);
Console.WriteLine(p2);
Player.ShowPlayerCount(); // called on the CLASS, not an object
Output
Anika (Score: 100)
Bob (Score: 85)
Total players in the game: 3
Note: 🔒 অ্যাক্সেস মডিফায়ারের (Access modifiers) চিট শিট বা ছোট্ট তালিকা: public = যে কেউ অ্যাক্সেস করতে পারবে। private = শুধু এই ক্লাসটিই অ্যাক্সেস করতে পারবে। protected = শুধু এই ক্লাসটি এবং এর চাইল্ড বা উত্তরাধিকারীরা অ্যাক্সেস করতে পারবে। internal = শুধু এই প্রজেক্টের ভেতরেই সীমাবদ্ধ। সব সময় private দিয়ে শুরু করুন এবং যখন খুব বেশি প্রয়োজন হবে, শুধু তখনই এর অ্যাক্সেস সবার জন্য উন্মুক্ত করে দিন। শুরুতেই সবকিছু উন্মুক্ত করে পরে আটকে দেওয়ার চেয়ে, প্রথমে নির্দিষ্ট করে পরে তা উন্মুক্ত করে দেওয়াটা অনেক সহজ।
চ্যালেঞ্জ

ছোট কুইজ

একটি ক্লাস (class) এবং একটি অবজেক্টের (object) মধ্যে পার্থক্য কী?
MethodsInheritance & Polymorphism