Java OOP হাতে কলমে, ব্যাংক অ্যাকাউন্ট প্রোগ্রাম বানিয়ে Class, Object, Encapsulation ও Inheritance শেখার সম্পূর্ণ পদ্ধতি

টিউন বিভাগ জাভা
প্রকাশিত

অবজেক্ট ওরিয়েন্টেড প্রোগ্রামিং শেখার সময় বেশিরভাগ শিক্ষার্থী সংজ্ঞা মুখস্থ করে ফেলেন। ক্লাস মানে নকশা, অবজেক্ট মানে সেই নকশা থেকে বানানো জিনিস, এই কথাগুলো সবাই বলতে পারেন। কিন্তু প্রশ্ন করলে বেশিরভাগই বলতে পারেন না, ফিল্ডটি private রাখলে বাস্তবে কী লাভ হলো, বা Inheritance না থাকলে কোন সমস্যায় পড়তাম।

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

যা যা লাগবে

  • কম্পিউটারে JDK 17 বা তার চেয়ে নতুন ভার্সন
  • IntelliJ IDEA Community Edition অথবা VS Code
  • জাভাতে মেথড লেখা ও লুপ চালানোর প্রাথমিক অভ্যাস
  • প্রতিটি কোড নিজে টাইপ করে রান করার ধৈর্য

যে প্রোগ্রামটি আমরা বানাব

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

  • প্রতিটি অ্যাকাউন্টের নিজস্ব নম্বর, গ্রাহকের নাম ও ব্যালেন্স থাকবে
  • ব্যালেন্স বাইরে থেকে কেউ সরাসরি বদলাতে পারবে না
  • জমা ও উত্তোলনের সময় নিয়ম যাচাই হবে, ভুল হলে বাংলায় বার্তা দেখাবে
  • একই তালিকায় দুই ধরনের অ্যাকাউন্ট রেখে একসাথে কাজ করা যাবে

ধাপ ১: Class লিখে Object তৈরি করা

ক্লাস হলো নকশা আর অবজেক্ট হলো সেই নকশা মেনে বানানো আসল জিনিস। একটি ক্লাস একবার লিখে আপনি হাজারটি অ্যাকাউন্ট বানাতে পারবেন, প্রতিটির তথ্য আলাদা থাকবে।

class BankAccount {private final String accountNumber; private final String holderName; private double balance;}
  • ফিল্ডগুলোকে private রাখছি, অর্থাৎ এগুলো শুধু এই ক্লাসের ভেতর থেকেই ছোঁয়া যাবে
  • অ্যাকাউন্ট নম্বর ও নামের সাথে final লিখেছি, কারণ অ্যাকাউন্ট খোলার পর এগুলো বদলানোর কথা নয়
  • ব্যালেন্স final নয়, কারণ এটি লেনদেনের সাথে সাথে বদলাবে

ধাপ ২: Constructor দিয়ে অ্যাকাউন্ট খোলা

Constructor হলো সেই বিশেষ মেথড যা অবজেক্ট তৈরির মুহূর্তে চলে। এর কাজ হলো নিশ্চিত করা যে অবজেক্টটি জন্মের সময়ই বৈধ অবস্থায় থাকে, অর্ধেক তথ্য নিয়ে যেন তৈরি না হয়।

 public BankAccount(String accountNumber, String holderName, double openingBalance) {this.accountNumber = accountNumber; this.holderName = holderName; this.balance = openingBalance;}
  • this শব্দটি বলছে বাঁ পাশের নামটি ক্লাসের ফিল্ড, আর ডান পাশেরটি প্যারামিটার
  • Constructor এর কোনো রিটার্ন টাইপ থাকে না, void ও লেখা যাবে না
  • নিজে একটিও Constructor না লিখলে জাভা একটি খালি Constructor নিজেই বানিয়ে দেয়

ধাপ ৩: Encapsulation দিয়ে ব্যালেন্স রক্ষা করা

এখন সবচেয়ে গুরুত্বপূর্ণ অংশ। ব্যালেন্স যদি public হতো, তাহলে প্রোগ্রামের যেকোনো জায়গা থেকে কেউ লিখে দিতে পারত ব্যালেন্স সমান দশ লাখ। Encapsulation মানে হলো ডেটা লুকিয়ে রেখে শুধু নিয়ন্ত্রিত পথে তাতে হাত দিতে দেওয়া।

 public void deposit(double amount) {if (amount <= 0) {System.out.println("জমার পরিমাণ শূন্যের বেশি হতে হবে"); return;} balance = balance + amount; System.out.println(amount + " টাকা জমা হয়েছে");} public void withdraw(double amount) {if (amount > balance) {System.out.println("ব্যালেন্স যথেষ্ট নয়"); return;} balance = balance - amount; System.out.println(amount + " টাকা উত্তোলন হয়েছে");} public double getBalance() {return balance;} public String getHolderName() {return holderName;}

এখানে আসল লাভটা কী হলো

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

ধাপ ৪: toString দিয়ে অবজেক্টকে পড়ার উপযোগী করা

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

 @Override public String toString() {return holderName + " (" + accountNumber + ") ব্যালেন্স " + balance;}

ধাপ ৫: Inheritance দিয়ে সেভিংস অ্যাকাউন্ট

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

class SavingsAccount extends BankAccount {private final double interestRate; public SavingsAccount(String accountNumber, String holderName, double openingBalance, double interestRate) {super(accountNumber, holderName, openingBalance); this.interestRate = interestRate;} public void addInterest() {double interest = getBalance() * interestRate / 100; deposit(interest);} @Override public void withdraw(double amount) {if (getBalance() - amount < 500) {System.out.println("সেভিংস অ্যাকাউন্টে অন্তত ৫০০ টাকা রাখতে হবে"); return;} super.withdraw(amount);}
  • super দিয়ে প্যারেন্ট ক্লাসের Constructor ডাকা হয়েছে, এটি চাইল্ড ক্লাসের প্রথম কাজ
  • withdraw মেথডটি নতুন করে লেখা হয়েছে, একে বলে মেথড ওভাররাইড
  • নিজের নিয়ম যাচাই শেষে super.withdraw ডেকে মূল কাজটি প্যারেন্টকেই করতে দেওয়া হয়েছে, ফলে কোড দুবার লিখতে হয়নি
  • ব্যালেন্স private বলে চাইল্ড ক্লাসেও getBalance মেথড দিয়েই মান নিতে হচ্ছে

ধাপ ৬: Polymorphism, এক তালিকায় দুই ধরনের অ্যাকাউন্ট

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

public class BankApp {public static void main(String[] args) {BankAccount current = new BankAccount("CA-1001", "নাছিরুল", 2000); SavingsAccount savings = new SavingsAccount("SA-2001", "রুমানা", 5000, 5); current.deposit(1500); current.withdraw(1000); savings.withdraw(4800); savings.addInterest(); BankAccount[] accounts = {current, savings}; for (BankAccount account : accounts) {System.out.println(account);}

প্রোগ্রামটি রান করলে কনসোলে নিচের লেখাগুলো আসবে। সেভিংস অ্যাকাউন্ট থেকে ৪৮০০ টাকা তোলার চেষ্টা আটকে গেছে, কারণ তাতে ব্যালেন্স ৫০০ এর নিচে নেমে যেত।

1500.0 টাকা জমা হয়েছে
1000.0 টাকা উত্তোলন হয়েছে
সেভিংস অ্যাকাউন্টে অন্তত ৫০০ টাকা রাখতে হবে
250.0 টাকা জমা হয়েছে
নাছিরুল (CA-1001) ব্যালেন্স 2500.0
রুমানা (SA-2001) ব্যালেন্স 5250.0

কমন ভুল ও সমাধান

Constructor এ super ডাকতে ভুলে যাওয়া

প্যারেন্ট ক্লাসে যদি প্যারামিটারসহ Constructor থাকে, তাহলে চাইল্ড ক্লাসে super দিয়ে সেটি ডাকা বাধ্যতামূলক। না ডাকলে কম্পাইলার বলবে প্যারেন্ট ক্লাসে খালি Constructor নেই। super এর লাইনটি অবশ্যই Constructor এর একদম প্রথম লাইনে বসাতে হবে।

private ফিল্ডে বাইরে থেকে হাত দেওয়ার চেষ্টা

account.balance লিখলে কম্পাইলার বলবে balance has private access। এটি ভুল নয়, বরং এটাই Encapsulation কাজ করছে তার প্রমাণ। মান দরকার হলে getBalance ব্যবহার করুন, বদলাতে চাইলে deposit বা withdraw ব্যবহার করুন।

টাকার হিসাবে double ব্যবহার করা

শেখার জন্য double ঠিক আছে, কিন্তু বাস্তব আর্থিক প্রজেক্টে দশমিকের হিসাবে সামান্য ভুল জমতে থাকে। সেখানে BigDecimal ব্যবহার করাই নিয়ম, অথবা টাকার হিসাব পয়সায় রূপ দিয়ে long টাইপে রাখা হয়।

শেষ কথা

খেয়াল করে দেখুন, আমরা একবারও OOP এর সংজ্ঞা মুখস্থ করিনি। তবু ক্লাস, অবজেক্ট, Constructor, Encapsulation, Inheritance আর Polymorphism, ছয়টি ধারণাই ব্যবহার হয়ে গেছে এবং প্রতিটির পেছনে একটি বাস্তব কারণ ছিল। এভাবে শিখলে পরীক্ষার খাতায় নয়, আসল প্রজেক্টেও কাজে লাগবে।

এবার আপনি নিজে চেষ্টা করুন, একটি LoanAccount ক্লাস বানান যেখানে ব্যালেন্স ঋণাত্মক হতে পারে। কোথায় আটকে যাচ্ছেন টিউমেন্টে জানান। এই প্রোগ্রামটি রান করে নিজেই নতুন নিয়ম যোগ করুন, তাহলেই OOP এর সুবিধাটি হাতে কলমে ধরা পড়বে।

Level 0

আমি নাছিরুল হক। বিশ্বের সর্ববৃহৎ বিজ্ঞান ও প্রযুক্তির সৌশল নেটওয়ার্ক - টেকটিউনস এ আমি 15 ঘন্টা 26 মিনিট যাবৎ যুক্ত আছি। টেকটিউনস আমি এ পর্যন্ত 9 টি টিউন ও 0 টি টিউমেন্ট করেছি। টেকটিউনসে আমার 0 ফলোয়ার আছে এবং আমি টেকটিউনসে 0 টিউনারকে ফলো করি।


টিউনস


আরও টিউনস


টিউনারের আরও টিউনস


টিউমেন্টস