সূচিপত্র

পর্ব দশে আমরা ইনহ্যারিটেন্স নিয়ে প্রাথমিক কিছু ধারণা পেয়েছিলাম। আজ জানবো ইনহ্যারিটেন্স নিয়ে বিস্তারিত।

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

class boxIn2D {
    public:
        void setWidth(int a) {
            width = a;
        }
        void setLength(int b) {
            length = b;
        }
        int getArea() {
            area = length*width;
            return area;
        }

    protected:
        int width;
        int length;
        int area;
};

এখন এই কোড যখন তুমি দেখালা, তখন সে খুব পছন্দ করে ফেললো। কিন্তু সে এবার বললো যে, তার শুধু ক্ষেত্রফল দিয়ে চলবে না। সে উচ্চতার ইনপুট দিয়ে তার আয়তনটাও চায়! তাও কাজ সোজা। ক্লাসটা এডিট করে ফেললেই হয়। কিন্তু সে এটুকু বলেই ক্ষান্ত দিল না। সে শর্ত জুড়ে দিল যে এই ক্লাসটার কোনো ধরণের পরিবর্তন আনা যাবে না! (Can you see where I am getting with this? ;))

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

আমরা ইতোমধ্যেই জানি যে ক্লাসটা আগে থেকে আছে, তা হল Base ক্লাস। আর যেটা নতুন করে বানাবো, সেটা হল Derived ক্লাস। Derived ক্লাস ডিফাইন করার জন্য আমাদের নিচের ফরম্যাটে একটা লাইন লিখতে হবেঃ

class derived-class: access-specifier base-class

আমাদের Derived ক্লাসের নাম দিলাম boxIn3D, এক্সেস স্পেসিফায়ার আছে তিন ধরণেরঃ public, private এবং protected, এই তিনটির তাৎপর্য আমরা একটু পরে জানছি। আপাতত আমরা public ব্যবহার করবো। আর base class এর নাম তো আমরা জানিই – boxIn2D

class boxIn3D: public boxIn2D {
    
};

এখন এই ক্লাসটা ইতোমধ্যেই boxIn2D ক্লাসের নন-প্রাইভেট মেম্বার length, width, area পেয়ে গেছে, এগুলো নতুন করে ডিক্লেয়ার করার দরকার নেই। আমরা নতুন দু’টি মেম্বার height, volume ডিক্লেয়ার করে নি।

class boxIn3D: public boxIn2D {
    protected:
        int height;
        int volume;
};

এগুলো protected করে রাখলাম, যাতে সরাসরি মেইন ফাংশন থেকে ডট অপারেটর দিয়ে এগুলো এক্সেস করা না যায়। তুমি চাইলে পাবলিকও রাখতে পার।

এবার আমাদের উচ্চতা আর ক্ষেত্রফলের জন্য মেথডটাও লিখে ফেলি।

class boxIn3D: public boxIn2D {
    public:
        void setHeight(int a) {
            height = a;
        }
        void setArea(int x) {
            area = x;
        }      
    protected:
        int height;
        int volume;
};

setArea মেথডটা লিখতে হয়েছে, যাতে মেইন ফাংশনে boxIn2D থেকে ক্ষেত্রফলটা রিটার্ন করে দেওয়া যায়। আশা করি এটা কেন করতে হচ্ছে সেটা বুঝে গেছ। এটা নিয়ে একটু চিন্তা কর। ইনহ্যারিটেন্স বুঝার জন্য এই কনসেপ্টটা অনেক গুরুত্বপূর্ণ।

এবার সবশেষে আয়তন বের করার মেথডটাও লিখে ফেলি। তাহলে পুরো ক্লাসটা দাঁড়াচ্ছে এমনঃ

class boxIn3D: public boxIn2D {
    public:
        void setHeight(int a) {
            height = a;
        }
        void setArea(int x) {
            area = x;
        }
        int getVolume() {
            volume = height * area;
            return volume;
        }        
    protected:
        int height;
        int volume;
};

আমাদের পুরো কোডটি হচ্ছে এমনঃ

#include <iostream>
using namespace std;
// Base Class
class boxIn2D {
   public:
      void setWidth(int a) {
         width = a;
      }
      void setLength(int b)
      {
         length = b;
      }

      int getArea() {
        area = length*width;
        return area;
      }
   protected:
      int width;
      int length ;
      int area;
};

// Derived class
class boxIn3D: public boxIn2D {
    public:
        void setHeight(int a) {
            height = a;
        }
        void setArea(int x) {
            area = x;
        }
        int getVolume() {
            volume = height * area;
            return volume;
        }
    protected:
        int height;
        int volume;
};
// main fucntion
int main(void) {
    int i;
    boxIn2D box;
    cout <<  "Length please: ";
    cin >> i;
    box.setLength(i);
    cout <<  "Width please: ";
    cin >> i;
    box.setWidth(i);

    // area print kortichi
    cout << "Area: " << box.getArea() << endl;

    boxIn3D box2;
    cout << "Height please: ";
    cin >> i;

    box2.setHeight(i);

    // area ta pathacchi boxIn3D class er moddhe
    /*amra box2 te prothom box er width ar length bebohar korechi, 
      tai box2 er area hishebe amra prothom box er area set korlam, 
       tumi chaile box2 er jonne alada alada length ar width dite paro */
    i = box.getArea();
    box2.setArea(i);

    // volume print kortichi
    cout << "Total Volume: " << box2.getVolume() << endl;

   return 0;
}

রান করেই দেখ ঠিক মত কাজ করে কি না! 😉

Access Control

একটা Derived Class এর Base ক্লাসের সবগুলো নন-প্রাইভেট মেম্বার এক্সেস করতে পারে। তাই, Base ক্লাসের যেসব মেম্বার Derived ক্লাসের থেকে হিডেন রাখতে চাও, সেগুলো তোমাকে অবশ্যই প্রাইভেট করে রাখতে হবে। নিচের সারিটা দেখলেই ব্যাপারটা বুঝতে পারবাঃ

Access Public Protected Private
Same Class Yes Yes Yes
Derived Class Yes Yes No
Outside Classes Yes No No

Derived ক্লাস Base ক্লাসের সবগুলো মেম্বারই ইনহেরিট(উত্তরাধিকার সূত্রে পায় 😀 ) করে, শুধু নিচের গুলো ছাড়াঃ

  • Base ক্লাসের constructors এবং destructor
  • Base ক্লাসের ওভারলোড করে দেওয়া অপারেটরগুলো
  • Base ক্লাসের ফ্রেন্ড
  • Base ক্লাসের private মেম্বার

তিন প্রকারের ইনহ্যারিটেন্স

আমরা আমাদের কোডে এক্সেস স্পেসিফায়ার দিয়েছিলাম public. এভাবে তিন ধরণের ইনহ্যারিটেন্স সম্ভবঃ

(১) পাবলিক ইনহ্যারিটেন্সঃ

  • Base ক্লাসের পাবলিক মেম্বারগুলো Derived ক্লাসের পাবলিক মেম্বার হয়ে যাবে।
  • Base ক্লাসের প্রোটেক্টেড মেম্বারগুলো Derived ক্লাসের প্রোটেক্টেড মেম্বার হয়ে যাবে।
  • Base ক্লাসের প্রাইভেট মেম্বারগুলো Derived ক্লাস কখনোই সরাসরি এক্সেস করতে পারবে না। তবে পাবলিক বা প্রোটেক্টেড কোনো মেম্বারের সাহায্যে পরোক্ষভাবে এক্সেস করতে পারবে।

(২) প্রোটেক্টেড ইনহ্যারিটেন্সঃ

  • Base ক্লাসের পাবলিক এবং প্রোটেক্টেড মেম্বারগুলো Derived ক্লাসের প্রোটেক্টেড মেম্বার হয়ে যাবে

(৩) প্রাইভেট ইনহ্যারিটেন্সঃ

  • Base ক্লাসের পাবলিক এবং প্রোটেক্টেড মেম্বারগুলো Derived ক্লাসের প্রাইভেট মেম্বার হয়ে যাবে

মাল্টিপল ইনহ্যারিটেন্স

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

কাজটা খুবই সোজা। ক্লাসটা হবে এরকমঃ

class weightConversion {
    public:
        void setShohog(int a) {
            shohog = a;
        }
        void setVolume(int b) {
            volume = b;
        }
        int getWeight() {
            weight = volume*shohog;
            return weight;
        }

    protected:
        int volume;
        int weight;
        int shohog;
};

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

দেখতেই পাচ্ছ, এবার দু’টি ক্লাসের জিনিস তোমার দরকার হচ্ছে নতুন ক্লাস বানাতে। মেজাজ খিচড়ে ওঠার কিছু নেই। তুমি চাইলে Derived ক্লাসে দু’টি ক্লাস থেকে ইনহ্যারিট করতে পার। এজন্য তোমাকে কমা দিয়ে Base ক্লাসগুলোর নাম পৃথক করে দিতে হবে। সাথে দিতে হবে স্পেসিফায়ারও। লিখতে হবেঃ

class derived-class: access baseA, access baseB....

তাহলে আমাদের নতুন ক্লাসটি হবেঃ

class cost: public weightConversion, public boxIn3D {
    public:
        void setDamPerEkok(int a) {
            ekEkokerDam = a;
        }
        void setWeight(int a) {
            weight = a;
        }
        int getCost() {
            return ekEkokerDam * weight;
        }
    protected:
        int ekEkokerDam;
};

এবার পুরো কোডটিও দেখে নেওয়া যাক!

#include <iostream>
using namespace std;
// Base Class
class boxIn2D {
   public:
      void setWidth(int a) {
         width = a;
      }
      void setLength(int b)
      {
         length = b;
      }

      int getArea() {
        area = length*width;
        return area;
      }
   protected:
      int width;
      int length ;
      int area;
};

// Derived class
class boxIn3D: public boxIn2D {
    public:
        void setHeight(int a) {
            height = a;
        }
        void setArea(int x) {
            area = x;
        }
        int getVolume() {
            volume = height * area;
            return volume;
        }
    protected:
        int height;
        int volume;
};
class weightConversion {
    public:
        void setShohog(int a) {
            shohog = a;
        }
        void setVolume(int b) {
            volume = b;
        }
        int getWeight() {
            return shohog*volume;
        }
    protected:
        int volume;
        int weight;
        int shohog;
};
class cost: public weightConversion, public boxIn3D {
    public:
        void setDamPerEkok(int a) {
            ekEkokerDam = a;
        }
        void setWeight(int a) {
            weight = a;
        }
        int getCost() {
            return ekEkokerDam * weight;
        }
    protected:
        int ekEkokerDam;
};
// main fucntion
int main(void) {
    int i;
    boxIn2D box;
    cout <<  "Length please: ";
    cin >> i;
    box.setLength(i);
    cout <<  "Width please: ";
    cin >> i;
    box.setWidth(i);

    // area print kortichi
    cout << "Area: " << box.getArea() << endl;

    boxIn3D box2;
    cout << "Height please: ";
    cin >> i;

    box2.setHeight(i);

    // area ta pathacchi boxIn3D class er moddhe
    i = box.getArea();
    box2.setArea(i);

    // volume print kortichi
    cout << "Total Volume: " << box2.getVolume() << endl;
    weightConversion boxx;
    cout << "Shohog Please: ";
    cin >> i;
    boxx.setShohog(i);
    i = box2.getVolume();
    boxx.setVolume(i);
    cout << "Total Weight: "<< boxx.getWeight() << endl;

    cost boxxx;
    cout << "Cost per unit please: ";
    cin >> i;
    boxxx.setDamPerEkok(i);
    i = boxx.getWeight();
    boxxx.setWeight(i);
    cout << "Total cost: " << boxxx.getCost() << endl;
    return 0;
}

উদাহারণটা একটু বড় হয়ে গেছে। তবে সময় নিয়ে বুঝে বুঝে পড়লে ইনহ্যারিটেন্সের ব্যাপারটা খুব ভাল ভাবেই বুঝবে আশা করি।

আউটপুটঃ

Snap 2015-07-25 at 16.06.08

সব ঠিকথাকভাবেই হল! আজ এ পর্যন্তই। কোনো প্রশ্ন থাকলে জিজ্ঞেস করতে দ্বিধা করবেন না। 🙂

Muntasir Wahed

Muntasir Wahed

System Administrator at স্বশিক্ষা.com
Jack of all trades, master of none.
Muntasir Wahed
Muntasir Wahed