Sunday, August 26, 2018

ডাটা স্ট্রাকচার - ৩ঃ লিঙ্ক লিস্ট

অ্যারে বনাম লিঙ্ক লিস্টঃ

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



লিঙ্ক লিস্টের কাজও মাল্টিপল ডাটা রাখা তবে কনসেপ্ট টা অ্যারের চেয়ে ভিন্ন। লিঙ্ক লিস্টে ভেরিয়েবলগুলো পাশাপাশি থাকেনা। কিন্তু পরে কোনটার পরে কোনটা থাকবে তা বলে দেওয়া থাকে। অথ্যাৎ, প্রতিটা ভেরিয়েবলে তার পরের জনের অ্যাড্রেস বলে দেওয়া থাকে। উপরের লিস্টই যদি আমি লিঙ্ক লিস্ট আকারে সাজাতে চাই তাহলে এমন হবে- 
এখানে ভেরিয়েবলগুলো পাশাপাশি থাকার কোন বাধ্যবাধকতা নাই। খেয়াল করো প্রতিটা নোডের দুইটা অংশ আছে। একটা অংশে তার ডাটা আর অন্য অংশে তারপরে কোন নোড থাকবে তার অ্যাড্রেস। প্রতিটা নোডেই এরকম ভেলু এবং তার পরের নোডের অ্যাড্রেস দেওয়া থাকে। যেহেতু যেকোন নোডে গেলেই পরের নোডের অ্যাড্রেস পেয়ে যাই সেহেতু আমরা সেই অ্যাড্রেস ধরে সবাইকে অ্যক্সেস করতে পারবো। বুঝতে সমস্যা হচ্ছে? দাঁড়াও বুঝিয়ে বলছি- 

মনে করো তোমরা ৪ বন্ধু- রহিম, করিম, রাকিব এবং সাকিব। একজন লোক তোমার বাড়ি অ্যড্রেস জানে। মনে করো লোকটার নাম সেফুদা। সেফুদাকে সবাই চিনে এবং মোটামুটি ওই এলাকার স্থায়ী। মনে করো ট্রাম্প নামের একজন ব্যক্তি তোমাদের সবার বাড়িতে আসতে চাচ্ছেন তথ্য সংগ্রহ করার জন্য। যেহেতু ট্রাম্প সেফুদাকে চিনে সেহেতু ট্রাম্প সেফুদার কাছ থেকে তোমার বাড়ির অ্যড্রেস টা জেনে নিলো। তারপর সেই অ্যড্রেস ধরে তোমার বাড়িতে চলে এলো এবং প্রয়োজনীয় তথ্য সংগ্রহ করলো। তোমার বাড়িতে আসার পর ট্রাম্প তোমার বন্ধুর অ্যড্রেস জিজ্ঞেস করলো তুমি রহিমের অ্যড্রেস বলে দিলে! তারপর তিনি রহিমের বাসায় গিয়ে করিমের অ্যড্রেস জানতে চাইলেন এবং চলে গেলেন করিমের বাসায়। তারপর রাকিবের বাসায় এবং শেষমেশ সাকিবের বাসায় গিয়ে আর কোন অ্যড্রেস পেলেননা এবং থেমে গেলেন। এভাবে সবার বাসায় তিনি চলে যেতে সক্ষম হলেন এবং সবার তথ্য সংগ্র করে ফেললেন। খেয়াল করো লোকটা কিন্তু এক এক করে তোমাদের সবার বাসায় চলে গেলো। এক্ষেত্রে তিনি কিভাবে গেলেন? তোমরা যে অ্যড্রেস বললে সেই অ্যড্রেস ধরেই! এখানে তোমরা তাঁকে দুইটা জিনিস দিয়েছো একটা হলো তোমাদের বাসার তথ্য যেটা ট্রাম্প সংগ্রহ করতে এসেছেন আরেকটা হল তোমার বন্ধুর অ্যড্রেস।  এখানে তোমরা প্রত্যেকেই একেকটি ভেরিয়েবল হিসেবে কাজ করেছো। লোকটার সবার বাড়িতে যাওয়ার পথ হল 
সেফুদা->রহিম->করিম->রাকিব->সাকিব। এই পথটা অন্য রকমও হতে পারতো। সেটা নির্ভর করে তোমরা কে কার অ্যড্রেস বলছো। 

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

 #include <stdio.h>  
 #include <stdlib.h>  
 struct Node  
 {  
   int data;  
   struct Node *next;  
 };  

নতুন যে ডাটা টাইপ তৈরী হল তা হচ্ছে- struct Node।  এটি এমন একটা ডাটা টাইপ যা একসাথে ইন্টেজার এবং একটা পয়েন্টার রাখতে পারে। কিন্তু আমরা চাইলে অন্যান্য প্রিমিটিভ ডাটা টাইপের মত (int, double, float) এক অক্ষরে করে নিতে পারি। এর জন্য আমাদের typedef নামক কিওয়ার্ড এর হেল্প নিতে হবে। এই কিওয়ার্ড দিয়ে একটা ডাটা টাইপকে রিনেম করার পদ্ধতি হল- 
typedef old_datatype new_datatype. যেমন উপরের struct Node কে যদি node এ কনভার্ট করতে চাই তাহলে লিখতে হবে- 

 typedef struct Node node  

এর ফলে node নামক একটি ডাটা টাইপ তৈরী হল যা দিয়ে আমরা এই টাইপের একটা ভেরিয়েবল ডিক্লেয়ার করতে পারি।

কথা হল- যেখানে অ্যারে আছে সেখানে এত ঝামেলায় যাওয়ার কি দরকার? আসলে অ্যারেতে কিছু সমস্যা আছে যে কারনে লিঙ্ক লিস্টের সুত্রাপাত।

যেমন ধরো, তুমি ১০০০০ স্টুডেন্ট এর তথ্য রাখার জন্য একটা সফটওয়্যার তৈরী করেছো। তুমি তথ্যগুলোগুলো ১০০০০ সাইজের একটা অ্যারেতে রেখেছো। তোমার তৈরী করা সফটওয়্যারটি ইউজারের কাছে চলে যাওয়ার পরে নিন্মোক্ত সমস্যার সম্মুখীন হতে পারে-
১। যদি কখনো ১০০০০ এর অধিক স্টুডেন্ট এর তথ্য রাখার দরকার পড়ে ইউজার তা করতে পারবেনা।
২। যদি ইউজারের স্টুডেন্ট কখনো ৫০০০০ এর অধিক না হয় তাহলে বাকি ৫০০০০ মেমরি অপচয় হবে
৩। ডাটাগুলো রিঅর্ডার করা কিম্বা মাঝখানে কোন ডাটা যুক্ত করা সময়সাপেক্ষ।

এই সমস্যাগুলো থেকে পরিত্রানের জন্য লিঙ্ক লিস্ট এসেছে। লিঙ্ক লিস্টে শুরুতে কোন ধরনের মেমরি এলোকেট করেনা। যখন দরকার হবে তখনই সে মেমরি এলোকেট করবে এবং ডাটা রাখবে। অথ্যাৎ, প্রয়োজন বেসিসে সে মেমরিতে যায়গা নিবে। যে পরিমান মেমরি দরকার সে সেই পরিমানই মেমরিতে যায়গা নিবে। এতে করে আমাদে উপরোক্ত প্রব্লেমগুলো সল্ভ হয়।
তো, ইতোমধ্যে আমরা জেনি  যে নোড নামের একটা ডেটা টাইপ আমাদের হাতে আছে। এই ডেটা টাইপ দিয়ে যদি কোন ভেরিয়েবল ডিক্লেয়ার করি সেই ভেরিয়েবল একইসাথে ডেটা রাখতে পারে এবং অন্য একটা নোডের অ্যাড্রেস রাখতে পারে। এই কথা বুঝতে পারলে লিংক লিস্ট ইমপ্লিমেন্টেশনের ৬০ ভাগ কাজ শেষ। উপরের গল্পটাকেই কোড আকারে লিখে ফেলি-

   node *Rahim, *Karim, *Rakib, *Sakib; //Declaring all node pointer variable to keep data  
   node *Sefuda, *Trump; //Declaring sefuda to keep the data of you/first person and Trump to travel all house  
   /*Allocating memory and keep data for all*/  
   Rahim = (node*)malloc(sizeof(node));  
   Rahim->data = 10;  
   Karim = (node*)malloc(sizeof(node));  
   Karim->data = 20;  
   Rakib = (node*)malloc(sizeof(node));  
   Rakib->data = 30;  
   Sakib = (node*)malloc(sizeof(node));  
   Sakib->data = 40;  
   Rahim->next = Karim; //Rahim can tell the address of next person Karim  
   Karim->next = Rakib; //Karim can tell the address of next person Rakib  
   Rakib->next = Sakib; //Rakib can tell the address of next person Sakib  
   Sakib->next = NULL; //There is no person after sakib. He tells NULL or none  
   Sefuda = Rahim;   //Sefuda knows the address of first person  
   Trump = Sefuda;   //Trump also knows the address of first person  
   /*Trump now visiting to all house */  
   while(Trump!= NULL)  
   {  
     printf("%d ", Trump->data);  
     Trump = Trump->next;  
   }  

এই কাজটাকে অন্যভাবেও করা যায়-
  sefuda = NULL; //Intially there is no person in the list. so, sefuda knows nothign  
   person = (node*)malloc(sizeof(node)); //create memory for first person  
   person->data = 10; //assigning data for first person Rahim  
   sefuda = person;  //Sefuda knows the first person  
   person->next = (node*)malloc(sizeof(node)); //creating memory for next person, Karim  
   person->next->data = 20; //Assigning data for Karim  
   person->next->next = (node*)malloc(sizeof(node)); //creating memory for next person Rakib  
   person->next->next->data = 30; //Assigning data for Rakib  
   person->next->next->next = (node*)malloc(sizeof(node)); //creating memory for sakib  
   person->next->next->next->data = 40; //assigning data for sakib  
   person->next->next->next->next = NULL; //There no person in next   
   //we can print all the data in same way  
   printf("%d ", person->data);  
   printf("%d ", person->next->data);  
   printf("%d ", person->next->next->data);  
   printf("%d ", person->next->next->next->data);  

অথবা এইভাবে -
 sefuda = NULL;  
   person = (node*)malloc(sizeof(node));  
   person->data = 10;  
   sefuda = person;  
   //person->next = (node*)malloc(sizeof(node));  
   //person->next->data = 20;  
   person->next = (node*)malloc(sizeof(node));  
   person = person->next;  
   person->data = 20;  
   //person->next->next = (node*)malloc(sizeof(node));  
   //person->next->next->data = 30;  
   person->next = (node*)malloc(sizeof(node));  
   person = person->next;  
   person->data = 30;  
   //person->next->next->next = (node*)malloc(sizeof(node));  
   //person->next->next->next->data = 40;  
   person->next = (node*)malloc(sizeof(node));  
   person = person->next;  
   person->data = 40;  
   //person->next->next->next->next = NULL;  
   person->next = NULL;  
   //we can print all the data in same way  
   printf("%d ", sefuda->data);  
   printf("%d ", sefuda->next->data);  
   printf("%d ", sefuda->next->next->data);  
   printf("%d ", sefuda->next->next->next->data);  

অথবা এইভাবে-
  int value, i;  
   sefuda = NULL;  
   for(i = 1; i<=4; i++)  
   {  
     scanf("%d", &value);  
     if(sefuda == NULL)  
     {  
       person = (node*)malloc(sizeof(node));  
       person->data = value;  
       person->next = NULL;  
       sefuda = person;  
     }  
     else  
     {  
       person->next = (node*)malloc(sizeof(node));  
       person = person->next;  
       person->data = value;  
       person->next = NULL;  
     }  
   }  

অথবা-
 int value, i;  
   sefuda = NULL;  
   for(i = 1; i<=4; i++)  
   {  
     scanf("%d", &value);  
     if(sefuda == NULL)  
     {  
       person = (node*)malloc(sizeof(node));  //creating first node   
       person->data = value;  //adding value   
       person->next = NULL;  //we don't know who is gonna next   
       sefuda = person; //let it know the sefuda/head that it is the first node   
     }  
     else  
     {  
       person = (node*)malloc(sizeof(node)); //allocating person for second node, which will replace previous value. No issue on that   
       person->data = value;  //adding value   
       person->next = sefuda; //next upcoming node will be pointing the sefuda/head  
       sefuda = person; //now second node became sefuda(first node) which pointing to the previous node   
     }  

Tuesday, August 7, 2018

অব্জেক্ট অরিয়েন্টেড প্রোগ্রামিং - ১১ঃ জাভা নেস্টেড ক্লাস

একটা ক্লাসের ভিতর এক বা একাধিক থাকলেই তাকে নেস্টেড ক্লাস বলে। সাধারনত একই ধরনের সবগুলো ক্লাসকে একটি ক্লাসের আন্ডারে নিয়ে আসার জন্য এই কাজটা করা হয়। যেমন একটা ইউনিভার্সিটির Student, Department, Faculty আমরা একটা ক্লাস University এর আন্ডারে নিয়ে আসতে পারি। নীচের প্রোগ্রামটি খেয়াল করো-

 public class University {  
      public class Student{  
            String studentName;  
            int studentAge;  
            String studentId;  
      }  
      public class Department{  
           String departmentName;  
           String departmentCode;  
      }  
      public class Faculty{  
           String facultyName;  
           String facultyId;  
      }  
      public class Staff{  
           String staffName;  
           String staffId;  
      }  
 }  

এখানে একটা ইউনিভার্সিটির জন্য লেখা সকল ক্লাসকে আলাদা আলাদা না লিখে একটা ক্লাসে লিখে ফেললাম। Inner ক্লাসের অব্জেক্ট তৈরী করতে হলে একটু ভিন্ন পন্থা অবলম্বন করতে হয়। Inner ক্লাসের রেফারেন্স Outer ক্লাসের রেফারেন্সের মাধ্যমে পাওয়া যায় আর Inner ক্লাসের কন্সট্রাক্টর আউটার ক্লাসের অব্জেক্ট এর মাধ্যমে পাওয়া যায়।

 OuterClassReference.InnerClassReference object_name = OuterClassObject.new InnerClass Constructor  

নীচের প্রোগ্রামটিতে University ক্লাসটির জন্য অব্জেক্ট তৈরী করা হয়েছে-

 public class MainClass {  
      public static void main(String[] args) {  
           University university_ob = new University();  
           University.Student student_ob = university_ob.new Student();  //creating student object
           University.Department department_ob = university_ob.new Department();  //creating department object
           University.Faculty faculty_ob = university_ob.new Faculty();  //creating faculty object
           University.Staff staff_ob = university_ob.new Staff();  //creating staff object
      }  
 }  

আবার আমরা না চাইলে অব্জেক্ট তৈরী করা ছাড়াও এসব ব্যবহার করতে পারি। সেক্ষেত্রে Inner ক্লাসগুলোকে Static করে দিলেই কাজ শেষ।

 public class University {  
      public static class Student{  
            static String studentName;  
            static int studentAge;  
            static String studentId;  
      }  
      public static class Department{  
           static String departmentName;  
           static String departmentCode;  
      }  
      public static class Faculty{  
           static String facultyName;  
           static String facultyId;  
      }  
      public static class Staff{  
           String staffName;  
           String staffId;  
      }  
 }  

 public class MainClass {  
      public static void main(String[] args) {  
           University university_ob = new University();  
           University.Student.studentName = "Rakib";  
           University.Department.departmentName = "CSE";  
           University.Faculty.facultyName = "Prf. xyz";  
      }  
 }  

দেখা যাচ্ছে শুধুমাত্র University দিয়ে তার সকল ডাটা আমি অ্যাক্সেস করতে পারছি। জিনিসটা অনেক সাজানো দেখাচ্ছে তাইনা? এভাবে অনেকগুলো ক্লাসকে একটা ক্লাসের আন্ডারে এনে সুন্দরভাবে অর্গানাইজ করা যায়।

সুবিধাসমুহঃ
১। ক্লাসগুলোকে গ্রুপিং করা যায়
২। যেহেতু ইনার ক্লাস থেকে আউটার ক্লাসের প্রাইভেট ফিল্ডগুলো অ্যাক্সেস করা যায় সেহেতু ইনক্যপসুলেশন আরো কার্যকরীভাবে অ্যাপ্লাই করা যায় ।
৩। নেস্টেড ক্লাসগুলো পড়ার উপযোগী এবং মেনেজ করা সহজ।

Monday, August 6, 2018

অব্জেক্ট অরিয়েন্টেড প্রোগ্রামিং - ১০ঃ জাভা this এবং super কিওয়ার্ড

আমরা সাধারনত জানি এক ক্লাস থেকে অন্য ক্লাসের ফিল্ড/ কন্সট্রাক্টর/মেথড ইউজ করতে হলে হলে তার অব্জেক্ট তৈরী করে সেই অব্জেক্ট এর মাধ্যমে অ্যাক্সেস করতে হয়।

কিন্তু ধরা যাক, এমন একটা পরিস্থিতি তৈরী হল যখন কোন ক্লাস থেকে তার সুপার ক্লাসের কোন ফিল্ড, কন্সট্রাক্টর বা মেথডকে কল করার প্রয়োজন পড়লো;  আবার এমন কোন পরিস্থিতি হল যখন একই ক্লাস থেকে ওই ক্লাসেরই কোন ফিল্ড, কনস্ট্রাক্টর, মেথডকে কল করার প্রয়োজন হল। তখন আমাদের super এবং this কিওয়ার্ড এর হেল্প নিতে হয়।

super কিওয়ার্ড হল এমন কিওয়ার্ড যা নির্দিষ্ট কোন ক্লাসের সুপার ক্লাস রেফারেন্স হিসেবে কাজ করে আর this কিওয়ার্ড দিয়ে একই ক্লাসের কন্সট্রাক্টর/ফিল্ড/মেথড কে কল করা হয়। মানে ওই ক্লাসের রেফারেন্স হিসেবে কাজ করে। এজন্য এদেরকে ডট দিয়েই অ্যাক্সেস করা যায়।

 public class Animal {  
      private String name;  
      private int age;  
      public Animal(String name, int age) {  
           this.name = name;  
           this.age = age;  
      }  
      public String getName() {  
           return name;  
      }  
      public int getAge() {  
           return age;  
      }  
 }  

 public class Human extends Animal {  
      private String gender;  
      public Human(String name, int age, String gender) {  
           super(name, age);   //instantiate using super class constructor   
           this.gender = gender; //instantiate it in here   
      }  
      public String getGender() {  
           return gender;  
      }  
      public void think()  
      {  
           System.out.println("Can think");  
      }  
 }  

Human ক্লাসে আমরা name এবং age কে ইনিসিয়াল করেছি সুপার ক্লাসের কন্সট্রাক্টরের সাহায্যে। কারন এটা অলরেডি ওখানে করা আছে। আর বাকি যেটা আছে তা আমরা এখানেই করে নিলাম। আবার খেয়াল করো আমরা কিন্তু this দিয়ে একই ক্লাসের gender কে কল করেছি। this এবং super এর কাজ একই শুধু পার্থক্য হল this কাজ করে একই ক্লাস হিসেবে আর super কাজ করে super ক্লাস হিসেবে।

 public class StartUp {  
      public static void main(String[] args) {  
           Human aHuman = new Human("Rakib", 23, "Male");  
           System.out.println(aHuman.getName());  
           System.out.println(aHuman.getAge());  
           System.out.println(aHuman.getGender());  
      }  
 }  

উপরের প্রোগ্রামটি রান করলে নিন্মোক্ত আউটপুট দেখাবেঃ
 Rakib  
 23  
 Male  

super এবং this দিয়ে যত ধরনের কল করা হয় তা এক দৃষ্টিতে দেখানো হলঃ



Thursday, August 2, 2018

অব্জেক্ট অরিয়েন্টেড প্রোগ্রামিং - ৯ঃ oop তে static কেন ব্যবহার করা হয়



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

প্রোগ্রাম- ১ঃ
 public class Student {  
      String name;  
      int age;  
      int university_code;  
 }  

 public class MainClass {  
      public static void main(String[] args) {  
           Student student1 = new Student();  
           Student student2 = new Student();  
           student1.age = 23;  
           student1.name = "Rakib";  
           student1.university_code = 100;  
           student2.name = "Rigan";  
           student2.age = 24;  
           student2.university_code = 100;  
           System.out.println("Name: "+ student1.name+", Age: "+student1.age+ ", University Code: "+ student1.university_code);  
           System.out.println("Name: "+ student2.name+", Age: "+student2.age+ ", University Code: "+ student2.university_code);  
      }  
 }  


OUTPUT
 Name: Rakib, Age: 23, University Code: 100  
 Name: Rigan, Age: 24, University Code: 100  

আমরা জানি প্রতিটা অব্জেক্টই মেমরিতে আলাদা আলাদা যায়গা করে নেয়। উপরে প্রোগ্রামটিতে যে ঘটনা ঘটেছিলো-

চিত্রঃ নন স্ট্যাটিক ফিল্ডগুলো অব্জেক্ট তৈরীর সাথে সাথে মেমরিতে আলাদা যায়গা নেয়

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

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

প্রোগ্রাম - ২ঃ
 public class Student {  
      static String name;  
      static int age;  
      static int university_code;  
 }  

 public class MainClass {  
      public static void main(String[] args) {  
           Student.name = "Rakib";  
           Student.age = 23;  
           Student.university_code = 100;  
           System.out.println("Name: "+ Student.name+ ", Age: "+ Student.age+ ", University Code: "+ Student.university_code);  
      }  
 }  

OUTPUT
Name: Rakib, Age: 23, University Code: 100  

লক্ষ্য করো এখানে কিন্তু কোন অব্জেক্ট তৈরী করিনি। সরাসরি ক্লাসনেম দিয়েই Student ক্লাস এর প্রোপার্টি গুলো পেয়ে যাচ্ছি। খেয়াল করো আমরা কিন্তু এখন দ্বিতীয় স্টুডেন্ট এর কোন ডাটা রাখতে পারছিনা। কারন এখানে কোন অব্জেক্ট তৈরী করা হয়নাই।  তাহলে অব্জেক্ট তৈরী করে দেখি কি ঘটনা ঘটে-

প্রোগ্রাম - ৩ঃ

 public class Student {  
      static String name;  
      static int age;  
      static int university_code;  
 }  

 public class MainClass {  
      public static void main(String[] args) {
  
           //Create object for student1  
           Student student1 = new Student();  

           //create object for student2  
           Student student2 = new Student();  

           //add data for student1  
           student1.age = 23;  
           student1.name = "Rakib";  
           student1.university_code = 100; 
 
           //add data for student2  
           student2.name = "Rigan";  
           student2.age = 24;  
           student2.university_code = 100; 
 
           //Print data for student1  
           System.out.println("Name: "+ student1.name+", Age: "+student1.age+ ", University Code: "+ student1.university_code);  

           //Print data for student2  
          System.out.println("Name: "+ student2.name+", Age: "+student2.age+ ", University Code: "+ student2.university_code);   
      }  
 }  

 OUTPUT  
 Name: Rigan, Age: 24, University Code: 100  
 Name: Rigan, Age: 24, University Code: 100  

খেয়াল করো দুইটা আলাদা আলাদা ডাটা দেওয়ার পরও আমরা শুধু Rigan এর ডাটাই দুইবার দেখতে পারছি। অথ্যাৎ, শেষে যে ডাটা টা দিলাম সেটাই দুইবার দেখাচ্ছে।

এটার কারন হল কোন ফিল্ড যখন static থাকে তখন সেটা আর অব্জেক্ট এর আন্ডারে থাকেনা।সেজন্যই দুইটা অব্জেক্ট এর জন্য name, age, এবং university_code এর আলাদা আলাদা যায়গা তৈরী হয়নি। তাই দুইজনের ডাটাই এক যায়গায় বা একই ভেরিয়েবলে অ্যাসাইন হয়েছে। আর আমরা সবাই জানি ভেরিয়েবলে সবসময় শেষের ডাটাই থাকে। নীচের ছবিটি খেয়াল করো-

চিত্রঃ স্ট্যাটিক ফিল্ডগুলো মেমরিতে একবারই যায়গা নেয়। যতবারই অব্জেক্ট তৈরী হোকনা কেন


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

প্রোগ্রাম - ৪ঃ
 public class Student {  
       String name;  
       int age;  
      static int university_code;  
 }  

 public class MainClass {  
      public static void main(String[] args) {  
           //Create object for student1  
           Student student1 = new Student();  
           //create object for student2  
           Student student2 = new Student();  
           //Setting university code   
           Student.university_code = 100;  
           //add data for student1  
           student1.age = 23;  
           student1.name = "Rakib";  
           //add data for student2  
           student2.name = "Rigan";  
           student2.age = 24;  
           //Print data for student1  
           System.out.println("Name: "+ student1.name+", Age: "+student1.age+ ", University Code: "+ student1.university_code);  
           //Print data for student2  
          System.out.println("Name: "+ student2.name+", Age: "+student2.age+ ", University Code: "+ student2.university_code);   
      }  
 }  

 OUTPUT  
 Name: Rakib, Age: 23, University Code: 100  
 Name: Rigan, Age: 24, University Code: 100  

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


এতে মেমরির অপচয় রোধ হল।  প্রথম প্রোগ্রামে university_code এর জন্য দুইবার মেমরি এলোকেট হয়েছে। অথ্যাৎ, মেমরিতে ৩২x২ = ৬৪ বিট যায়গা দখল হয়েছে। যদি আমি মোট ১০০ টা অব্জেক্ট তৈরী  করতাম তাহলে ৩২x১০০ = ৩২০০ বিট যায়গা দখল হতো। যা অপ্রয়োজনীয়।

কিন্তু প্রোগ্রাম - ৪ যতটা অব্জেক্ট তৈরী হোকনা কেন university_code এর জন্য মাত্র ৩২ বিটেই সকল অব্জেক্ট এর কাজ হয়ে যাবে। এতে আমাদের অপ্রয়োজনীয় মেমরি তৈরী করার দরকার পড়েনাই। মেমরি লস কমে গেছে।

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


Friday, July 27, 2018

অবজেক্ট অরিয়েন্টেড প্রোগ্রামিং - ৮ঃ এসোসিয়েশন রিলেশনশিপ


একটা ক্লাসের অবজেক্টকে যদি অন্য ক্লাসে ডাটা ফিল্ড হিসেবে ইউজ করতে চাই সেক্ষেত্রে দুই ক্লাসের মধ্যে যে সম্পর্ক তৈরী হয় তাই হল এ্যাসোসিয়েশন রিলেশনশীপ।

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

আমরা প্রিমিটিভ ডাটা যেমন integer, double, float ইত্যাদি টাইপের ডাটা রাখার জন্য সিমপ্লি ঐ নামের ভেরিয়েবল ডিক্লেয়ার করলেই কাজ হয়ে যায়। কাজটা অনেক সোজা কারন ইন্টেজার, ডাবল, ফ্লোট এসব প্রিমিটিভ টাইপ এবং এদেরকে ভাংলে অন্য কোন ডাটা টাইপ খুঁজে পাওয়া যাবেনা। এদেরকে সরাসরি অ্যসাইনমেন্ট অপারেটর দিয়ে অ্যাসাইন করে ফেলা যায়। কিন্তু কাস্টমাইজড ডাটা টাইপের ভেতর অনেকগুলো প্রিমিটিভ ডাটা ফিল্ড এবং মেথড থাকতে পারে। সেটা ডট দিয়ে অ্যাক্সেস করা যায় তা আমরা অলরেডি জানিই।

এ্যাসোসিয়েশন মোটামুটি ২ ধরনের-

১। এগ্রেগেশন(Aggregation) 

আমরা জানি, একটা ইউনিভার্সিটির প্রতিটা ডিপার্টমেন্ট এর আন্ডারে অনেকগুলো স্টুডেন্ট থাকে। সেহেতু ডিপার্টমেন্ট এর আন্ডারে একটা স্টুডেন্ট এর লিস্ট থাকবে। ব্যপারটা UML আকারে দেখার চেষ্টা করি-


এই দুটির জন্য দুটো ক্লাস আমরা কোডে লিখার চেষ্টা করবো-

 public class Student {  
   private String studentId;   
   private String studentName;   
   private String studentDept;   
   public Student(String studentId, String studentName, String studentDept) {   
      this.studentId= studentId;   
      this.studentName= studentName;   
      this.studentDept= studentDept;   
   }  
      public String getStudentId() {  
           return studentId;  
      }  
      public String getStudentName() {  
           return studentName;  
      }  
      public String getStudentDept() {  
           return studentDept;  
      }  
 }  

 import java.awt.List;  
 import java.util.ArrayList;  
 public class Department {  
    private String departmentName;   
    private ArrayList<Student> studentList;   
    public Department(String departmentName, ArrayList<Student> studentList) {   
      this.departmentName = departmentName ;   
      this.studentList = studentList;   
    }   
    public ArrayList<Student> getAllStudents() {   
      return studentList;   
    }   
 }  

 import java.awt.List;  
 import java.util.ArrayList;  
 public class MainClass {  
      public static void main(String[] args) {  
           Student student1 = new Student("111", "Rakib", "CSE");  
           Student student2 = new Student("222", "Sakib", "CSE");  
           Student student3 = new Student("333", "Rigan", "CSE");  
           Student student4 = new Student("444", "Sezan", "CSE");  
           ArrayList<Student> studentList = new ArrayList<Student>();  
           studentList.add(student1);  
           studentList.add(student2);  
           studentList.add(student3);  
           studentList.add(student4);  
           Department cse_department = new Department("CSE", studentList);  
           ArrayList<Student> allStudent = cse_department.getAllStudents();  
           for(Student aStudent: allStudent) {  
                System.out.println(aStudent.getStudentName()+" "+ aStudent.getStudentDept());  
           }  
      }  
 }  

মেইন ক্লাস থেকে কল পরার নিন্মোক্ত আউটপুট আসবেঃ

 Rakib CSE  
 Sakib CSE  
 Rigan CSE  
 Sezan CSE  


যেহেতু আমরা Student ক্লাস Department ক্লাসে ডাটা ফিল্ড হিসেবে ইউজ করেছি সেহেতু Student ক্লাস এবং Department ক্লাসের মধ্যে এ্যাসোসিয়েশন রিলেশনশীপ তৈরি হল। একটা ডিপার্টমেন্টে অনেকগুলো রাখার জন্য আমরা অ্যারে লিস্ট ব্যবহার করেছি।

যেহেতু এই রিলেশনশীপ একমুখী অথ্যাৎ ডিপার্টমেন্ট ক্লাস স্টুডেন্ট ক্লাসের উপর ডিপেন্ডেন্ট কিন্তু স্টুডেন্ট ক্লাস ডিপার্টমেন্ট ক্লাসের উপর ডিপেন্ডেন্ট নয়। মানে হল ডিপার্টমেন্ট ক্লাস যদি না থাকে তাহলে স্টুডেন্ট ক্লাসের কিছু হবেনা কিন্তু স্টুডেন্ট ক্লাস না থাকলে ডিপার্টমেন্ট ক্লাস দিয়ে লাভ হবেনা। কারন ডিপার্টোমেন্ট ক্লাস স্টুডেন্ট ক্লাসকে ব্যবহার করেছে বা স্টুডেন্ট ক্লাসের উপর ডিপেন্ডেন্ট আছে। একে Aggregation বলা হয়।

২। কম্পোজিশন(Compotion)

কম্পোজিশনে দুইটা এন্টিটি বা ক্লাস পরস্পর পরস্পরের উপর ডিপেন্ডেন্ট। অথ্যাৎ, কোন একটা বাদ দিলে প্রোগ্রাম সঠিকভাবে কাজ করবেনা। ব্যপারটা অনেকোটা লাইব্রেরীর মত। আমরা জানি প্রতিটা লাইব্রেরিতে অনেকগুলো বই থাকে, লাইব্রেরী ছাড়া বই কল্পনা যায়না তার মানে লাইব্রেরীর উপর বই ডিপেন্ডেন্ট। আবার বই ছাড়া কি লাইব্রেরী কল্পনা করা যায়? বই থাকে বলেই একে লাইব্রেরী বলা হয়। সো, এখানে পরস্পর পরস্পরের উপর হাইলি ডিপেন্ডেন্ট। 

একটা বই এর নাম এবং টাইটেল থাকতে পারে। আবার একটা লাইব্রেরিতে থাকতে পারে বই এর লিস্ট। এটাও আমরা UML এর মাধ্যমে দেখার চেষ্টা করি-



পুরো ব্যপারটা আমরা কোডে লিখার চেষ্টা করি-

 public class Book {  
      private String name;  
      private String author;  
      public Book(String title, String author) {  
           this.name = title;  
           this.author = author;  
      }  
      public String getName() {  
           return name;  
      }    
      public String getAuthor() {  
           return author;  
      }   
 }  

 import java.awt.List;  
 import java.util.ArrayList;  
 public class Library {  
      private ArrayList<Book> bookList;  
      public Library(ArrayList<Book> bookList) {  
           this.bookList = bookList;  
      }  
      public ArrayList<Book> getAlllBooksFromLibrary(){  
          return bookList;   
       }  
 }  

 import java.util.ArrayList;  
 public class MainClass {  
     public static void main(String[] args) {  
     Book book1 = new Book("Complete Reference Java", "Herbert Schield");  
     Book book2 = new Book("Under the Sea", "Daniel Dipo");  
     ArrayList<Book> bookList = new ArrayList<Book>();  
     bookList.add(book1);  
     bookList.add(book2);  
     Library aLibrary = new Library(bookList);  
     ArrayList<Book> allBooks = aLibrary.getAlllBooksFromLibrary();  
     for(Book book : allBooks){  
       System.out.println(book.getName() + " by " + book.getAuthor());  
     }  
      }  
 }  

মেইন ক্লাস থেকে কল করার পর নিন্মোক্ত আউটপুট পাওয়া যাবেঃ
OUTPUT
Complete Reference Java by Herbert Schield  
 Under the Sea by Daniel Dipo  

Tuesday, July 10, 2018

মহাবিশ্ব ও আমরা - ১ঃ পৃথিবী থেকে শুন্যে


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

একটু বুঝিয়ে বলি, মনে করুন আপনি গাড়িতে ভ্রমন করেতেছেন যা ৫০কিমি/সেকেন্ডে সুষম বেগে চলছে। কিন্তু কিভাবে বুঝলেন গাড়িটি চলছে বা এত কিমি বেগে চলছে? স্থির কোন গাড়ি গাছপালার দিকে তাকালেই বুঝা যায় গাড়িটি আসলে চলছে তাইনা? তাছাড়া কোন যন্ত্র ছাড়া বোঝা সম্ভব? সেই স্থির গাড়িটি যদি ৫০ কিমি বেগে বিপরীত দিকে যাত্রা করে তাহলে আপনার গাড়িটির গতিবেগ কত মনে হবে? নিশ্চিৎ ১০০। আবার সেই গাড়িটি যদি ৫০ কিমি বেগে যদি একই দিকে যাত্রা করে তাহলে আপনার গাড়ির গতি কত মনে হবে? নিশ্চিৎ শূন্য! বিশ্বাস না হলে আজই পরীক্ষা করে দেখুন! অথ্যাৎ, ভিবিন্ন প্রসঙ্গ কাঠামোর সাপেক্ষে বস্তুর স্পিড ভিবিন্ন রকম হচ্ছে! অদ্ভুত না?

গাড়ির গতির সাথে সাথেই আমাদের শরীররও সমান গতিপ্রাপ্ত হয়। যে কারনে গাড়ি হঠাৎ ব্রেক কষলে আমরা পেছনের দিকে চলে যাই। এটার প্রমাণ পাওয়া যাবে যদি কোন চলন্ত গাড়ির ছাদে বসে উপরের দিকে কোন বস্তুকে নিক্ষেপ করা হয় তা আবার হাতেই ফিরে আসবে। আরেকটু সহজ করে বলি- ৫০ কিমি/সেকেন্ডে বেগে চলা গাড়ি থেকে যদি কোন বস্তু উপরের দিকে নিক্ষেপ করা হয় তাহলে এক সেকেন্ড পরে তা হাতেই ফিরে আসবে। এটা কিভাবে সম্ভব? কারন এক সেকেন্ড পরে গাড়িতো ৫০ কিমি দূরে চলে যাবে যেখানে বস্তুটি আগের অবস্থায় থাকার কথা কারন বস্তুটির সাথে গাড়ি কিম্বা হাতের কোন স্পর্শ ছিলনা। এটার কারন হল আমাদের হাত গাড়ির সাথে সমান গতিপ্রাপ্ত একই সাথে সেই বস্তুটাও! যে কারনে বস্তুটি হাওয়ায় ঐ ৫০ কিমি অতিক্রম করে আমাদের হাতেই ফিরে আসবে। শরীরের গতিবেগের সাথে মানসিক তারতম্যের কারনেই অনেকে গাড়িতে বমি বমি অনুভব করেন বা বমি করেন। এসবই আপেক্ষিকতার কারন।

কখনো নিজেকে প্রশ্ন করেছেন কেন কোন বস্তুকে দূর থেকে অপেক্ষাকৃত ছোট মনে হয়? ভূমি থেকে সব বস্তুকে এত ছোট দেখায় কেন? মানুষগুলো পিপড়া সাইজের দেখা যায় কেন? এটাও যে একধরনের রিলেটিভিটি তা বললেও ভূল কিছু হবেনা। যাইহোক আমরা সেই বিতর্কে না যাই। যদিও এটার মুল কারন হল বস্তুর সাথে পর্যবেক্ষকের কৌনিক ব্যবধান-
কৌনিক পার্থক্যের কারনে আমরা দূর থেকে কোন জিনিসকে ছোট দেখি
এখন কথা হল ১৩ তলা বিল্ডিং এর ছাদ থেকে মানুষগুলো সহ সবকিছুকে এত এত ক্ষুদ্র মনে হয় সেই সাথে আমরা অনেকগুলো বস্তুকে একসাথে দেখতে পাচ্ছি তাইনা? ঢাকা শহরের কোন ১৩ তলা বিল্ডিং এর ছাদ থেকে মোটামুটি পুরো ঢাকা শহরকে দেখতে পাওয়া যাবে এবং সেই সাথে মানুষগুলো সহ সমস্ত কিছু অপেক্ষাকৃত ক্ষুদ্র মনে হবে।
ড্রোন থেকে আমাদের ঢাকা শহর

কখনো কি ভেবে দেখেছেন আমরা যদি ক্রমাগত উপরের দিকে উঠতে থাকি তাহলে আমাদের ঢাকা শহরকে কেমন দেখাবে? কিম্বা উপরে উঠতে গেলে আমাদের কি কি জিনিস ফেস করতে হবে? আমরা জানি আমাদের পৃথিবী বায়ুমন্ডলে আবদ্ধ। উপরে উঠতে গেলে আমাদের এই বায়ুমন্ডলের মধ্য দিয়েই অতিক্রম করতে হবে। দুরত্ব এবং বায়ুমন্ডলের উপাদানের উপর ভিত্তি করে এই বায়ুমন্ডলকে মোটামুটি ৫ ভাগে ভাগ করা হয়েছে। অথ্যাৎ, নির্দিষ্ট দুরত্বে উপরে উঠতে গেলে আমাদের এই ৫ টি অঞ্চল ফেস করতে হবে।
পৃথিবীর বায়ুমন্ডলের ভিবিন্ন স্তর 

ট্রপোস্ফিয়ারঃ ০ থেকে ১২ কিলোমিটার (০ থেকে ৭ মাইল)
স্ট্র্যাটোস্ফিয়ারঃ ১২ থেকে ৫০ কিলোমিটার (৭ থেকে ৩১ মাইল)
মেসোস্ফিয়ারঃ ৫০ থেকে ৮০ কিলোমিটার (৩১ থেকে ৫০ মাইল)
থার্মোস্ফিয়ারঃ ৮০ থেকে ৭০০ কিলোমিটার (৫০ থেকে ৪৪০ মাইল)
থার্মোস্ফিয়ারঃ >৭০০
এক্সোস্ফিয়ারঃ <৭০০ কিলোমিটার

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

মোটামুটি ভূপৃষ্ট থেকে ১০০০ কিলোমিটার উপরে উঠে যাওয়ার পর আমরা স্বাভাবিকভাবে আর পৃথিবীতে ফেরত আসবোনা। এখানে আমরা ভাসতে থাকবো। এই অঞ্চলকেই বলা হয় মহাকাশ। এই অঞ্চলের কোন শেষ নেই। এই মহাকাশের বিস্তার কতটূকু তা আজ পর্যন্ত মানুষের দ্বারা বের করা সম্ভব হয়নি।

ছবিটি ইন্টারন্যাশনাল স্পেস স্টেশন থেকে তোলা 

আমরা সবাই জানি মহাকাশে ইন্টারন্যাশনাল স্পেস স্টেশন নামে একটা কৃত্রিম উপগ্রহ আছে। মহাকাশ নিয়ে গবেষনার জন্য ১৯৯৮ সালে এটি চালু করা হয়। পৃথিবীর প্রায় ১৬ টি দেশ নিয়ে গঠিত এই কৃত্রিম উপগ্রহটি পৃথিবী থেকে ৪০৮ কিলোমিটার দূরে অবস্থিত।  জিরো গ্র্যাভিটিতে বা ভাসমান অবস্থায় মানুষ এখানে কিভাবে থাকে তা সম্পর্কে স্পষ্ট ধারনা পাওয়া যাবে এই ভিডিওতে-



পরবর্তীতে মহাকাশ সম্পর্কিত আরো দারুন কিছু বিষয় নিয়ে কথা হবে।

Thursday, June 28, 2018

ডাটা স্ট্রাকচার - ২ঃ অ্যারের ভিতর বাহির


যদি তোমাকে বলা হয় ৫০ টা নাম্বার একত্রে যোগ করে দাও তাহলে তুমি কি করবে? তুমি কি আগের মত ৫০ টা ভেরিয়েবল ডিক্লেয়ার করে তারপর ইনপুট নিবে? কখনোই না। কারন এটা সময় সাপেক্ষ!

তাহলে আমাদের এমন একটা অবস্থা থাকা দরকার যা দ্বারা আমরা খুব দ্রুত অনেকগুলো ভেরিয়েবল ডিক্লেয়ার করে ফেলতে পারবো! হ্যাঁ, একটা ফিচার আছে যার নাম অ্যারে।  অ্যারে ডিক্লেয়ার করার নিয়মটা হল-  Data_Type variable_name[size]; নীচের উদাহরনটা দেখো-

int value[50];
এটা দেওয়ার সাথে সাথেই কিন্তু ৫০ টা ভেরিয়েবল ডিক্লেয়ার হয়ে গেছে। এই ভেরিয়েবলগুলো হল-
value[0],value[1],value[2],value[3],value[4],value[5],value[6],value[7],value[8],value[9].........value[49]
ব্র্যাকেটের ভেতরের সাইজ পরিবর্তন করে এভাবে আমরা যেকোন পরিমান ভেরিয়েবল তৈরী করে ফেলতে পারি। লুপ চালিয়ে খুব সহজভাবেই আমরা এর ভেতরে ডাটা রাখতে পারি এবং ডাটা দেখতে পারি।  নীচের প্রোগ্রামটি খেয়াল করো-

Program - 1: Input 5 numbers in an array and sum it

 #include <stdio.h>  
 int main()  
 {  
   int num[5], i, sum = 0;  
   for(i = 0; i<5; i++)  
   {  
     scanf("%d", &num[i]);  
   }  
   for(i = 0; i<5; i++)  
   {  
     sum+= num[i];  
   }  
   printf("Sum: %d\n", sum);  
   return 0;  
 }  

 Input:   
 10 20 30 40 50   
 Output  
 150  

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

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

Program - 1: Print the Memory of an array and normal variables 

 #include <stdio.h>  
 int main()  
 {  
   int i, num[10], sum = 0;  
   printf("Memory Address of array: ");  
   for(i = 0; i<10; i++)  
   {  
     printf("%d ", &num[i]);  
   }  
   printf("\n");  
   printf("Memory address of variables: ");  
   printf("%d %d\n", &i, &sum);  
   return 0;  
 }  

 Output:   
 Memory Address of array: 6356708 6356712 6356716 6356720 6356724 6356728 6356732 6356736 6356742 6356744  
 Memory address of variables: 6356748 6356724  

উপরে দেখা যাচ্ছে অ্যারের মেমরি অ্যাড্রেস একটা সিকুয়েন্স মেন্টেন করে চলছে। প্রতিটা মেমরি অ্যাড্রেসের পার্থক্য ৪ করে। কিন্তু ভেরিয়েবলের ক্ষেত্রে ব্যাপারটা অন্য রকম। আমরা যত ভেরিয়েবলই ডিক্লেয়ার করিনা কেন তা পাশাপাশি থাকবে কি থাকবেনা তার কোন গ্যারান্টি নাই। অথ্যাৎ, তাদের অবস্থান বা সিকুয়েন্স এর উপর আমাদের কোন নিয়ন্ত্রন নাই। যেটা অ্যারের ক্ষেত্রে পাওয়া যায়। অ্যারের সাইজ যতই হোক না কেন এটা যে নিশ্চিৎ যে সবগুলো ভেরিয়েবল পাশাপাশি অবস্থান করবে। এই অ্যারেটা যদি আমরা ভিজুলাইজ করি তাহলে এমন দেখাবে-
অ্যারের আরেকটা মজার বৈশিষ্ট্য হল অ্যারের নামটা পয়েন্টার হিসেবে কাজ করে এবং সেই পয়েন্টারে প্রথম ভেরিয়েবলটার অ্যাড্রেস থাকে। সেই অনুযায়ী উপরে num হল একটি পয়েন্টার এবং এর কছে num[0] এর অ্যাড্রেস থাকে। বিশ্বাস না হলে num[0] এর মেমরি অ্যাড্রেস এবং পয়েন্টারটা প্রিন্ট করে দেখো। 

অ্যারের এই বৈশিষ্ট্যটা কাজে লাগিয়ে আমরা ইন্ডেক্সিং এবং & ছাড়াই ডাটা ইনপুট এবং আউটপুট দেখাতে পারি। নীচের প্রোগ্রামটি খেয়াল করো- 

Program - 3: Input 10 numbers in an array and print it. Don't use any ampersand or array indexing 

 #include <stdio.h>  
 int main()  
 {  
   int i, num[10], sum = 0;  
   int *ptr = num;  
   for(i = 0; i<10; i++)  
   {  
     scanf("%d", ptr);  
     ptr++;  
   }  
   ptr = num;  
   for(i = 0; i<10; i++)  
   {  
     printf("%d ", *ptr);  
     ptr++;  
   }  
   return 0;  
 }  

 INPUT   
 10 20 30 40 50 60 70 80 90 100  
 OUTPUT  
 10 20 30 40 50 60 70 80 90 100  

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

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

একদম শুরুতে num এবং ptr প্রথম অবস্থানে থাকে এবং  ptr প্রতিবার এক এক করে  বাড়াতে বাড়াতে সবগুলো অ্যাড্রেসে যেতে পারছে এবং সেই পার্টিকুলার অ্যাড্রেসের ডাটা নিতে বা রাখতে পারছে। একে পয়েন্টিং বলা হয় আর ptr বা num কে পয়েন্টার বলা হয়। এভাবে একটা লিস্ট বা অ্যারের শেষ পর্যন্ত সে ট্রাভেল করতে পারে। এভাবেই অ্যারে কাজ করে। আশাকরি বুঝতে সমস্যা হয়নাই।

প্র্যাক্টিস প্রব্লেমঃ
১। ট্রাম্প যদি গনু মোল্লাকে নিয়েই সবগুলো বাড়িতে যেতেন তাহলে কি সমস্যা হতো, উত্তর জানাও কমেন্টে।

Wednesday, March 28, 2018

অবজেক্ট অরিয়েন্টেড প্রোগ্রামিং - ৭ঃ ইন্টারফেস

ইন্টারফেস অনেকটা অ্যাবস্ট্র্যাক্ট ক্লাসের মতই তবে এর ভেতরে কোন কনক্রেট মেথড থাকেনা। মানে হল সবগুলো মেথডই এখানে অ্যাবস্ট্র্যাক্ট। ইন্টারফেস মানেই যেহেতু অ্যাবস্ট্র্যাক্ট সেহেতু এর ভেতরে কোন মেথডকে অ্যাবস্ট্র্যাক্ট লিখে দেওয়ার দরকার পড়েনা। আমরা সেই Animal উদাহরনে ফিরে যাই-

এই উদাহরনে যদি একটু ভালোভাবে খেয়াল করি প্রতিটা Animal এর হাটার ধরন এবং কথা বলার ধরন একই রকম না। তাহলে এই দুটো মেথডের ইমপ্লিমেন্টেশন সব ক্লাসের জন্য একই হবেনা তাইনা? যেমন পৃথিবীর সব প্রাণী যদি Animal ক্লাসকে ইনহেরিট করে তাহলে এখানে অসামঞ্জস্যতা ক্রিয়েট হবে। এখানে আমরা এইটুকু নিশ্চিত যে প্রতিটি প্রাণী হাটতে এবং কথা বলতে পারে কিন্তু আমরা এটা নিশ্চিত না তাদের কার হাটার ধরন কেমন এবং কার কথা বলার ধরন কেমন। যেটুকু নিশ্চিত আমরা সেটুকুই লিখে দেই। তাহলে আমরা এই দুটো মেথডকে আন-ইমপ্লিমেন্টেড লিখে রাখবো কারন আমরা এখনো নিশ্চিত না বডিতে কি লিখতে হবে। যেহেতু সব মেথডই এখানে আন-ইমপ্লিমেন্টেড সেহেতু পুরো ক্লাসকে আমরা ইন্টারফেস হিসেবে রাখতে পারি। তাতে বার বার অ্যাবস্ট্র্যাক্ট লিখা লাগবেনা। ইন্টারফেসের ক্ষেত্রে extends এর পরিবর্তে লিখতে হয় implements তো আমরা কাজটি করেই ফেলি-

 public interface Animal {  
      public void Walk();  
      public void Speak();  
 }  
 public class Human implements Animal {  
      public void Walk()  
      {  
           System.out.println("Human walk using two legs");  
      }  
      public void Speak() {  
           System.out.println("Human can speak using- Hi, Hello");  
      }  
 }  
 public class Dog implements Animal {  
      public void Walk() {  
           System.out.println("Dog walk using two legs");  
      }  
      public void Speak() {  
           System.out.println("Dog can speak something like Woof");  
      }  
 }  
 public class StartUp {  
      public static void main(String[] args) {  
           Human human1 = new Human();  
           human1.Walk();  
           human1.Speak();  
           Dog dog1 = new Dog();  
           dog1.Walk();  
           dog1.Speak();  
      }  
 }       
 OUTPUT  
 Human walk using two legs  
 Human can speak using- Hi, Hello  
 Dog walk using two legs  
 Dog can speak something like Woof  

ইন্টারফেস কেন দরকারঃ
১। টিমওয়ার্কে সকল টিম মেম্বারদের একটা নিয়মের মধ্যে রাখাঃ মনে করো তুমি একজন প্রোজেক্ট লিডার। তুমি একটি প্রোজেক্ট করতে যাচ্ছো যেখানে অনেক গুলো ক্লাস লিখতে হবে। একেকটা ক্লাসের দায়িত্ব একেকজন মেম্বারকে দিয়ে দিয়েছো।  তুমি চাচ্ছো সবগুলো ক্লাসে এমন কিছু জিনিস থাকতেই হবে। তুমি সিমপ্লি একটা ইন্টারফেস লিখে দিলে এবং সবাইকে বলে দিবে সবাই যেন ঐ ইন্টারফেসটা Implement করে। এখন সেই ইন্টারফেসটা ইমপ্লিমেন্ট করতে গেলে তাকে অবশ্যই সেই জিনিসগুলো ইমপ্লিমেন্ট করতে হবে যা তুমি ইন্টারফেসের ভিতর লিখে দিয়েছো :D
এতে তিনটা লাভ হল- সবাই ঐ মেথডগুলো লিখতে হবে, মেথডগুলোর নাম একই ইউজ করবে। কেউ রাম, কেউ সাম কেউ যদুমদু লিখার সুযোগ পাবেনা :D

২। মাল্টিফল ইনহেরিটেন্সঃ জাভাতে মাল্টিফল ইনহেরিটেন্স সাপোর্ট করেনা। কিন্তু ইন্টারফেস ইউজ করে তুমি একাধিক interface ইমপ্লিমেন্ট করতে পারবে।

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

Tuesday, March 27, 2018

অবজেক্ট অরিয়েন্টেড প্রোগ্রামিং - ৬ঃ অ্যাবস্ট্রেকশন


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

 public abstract void exampleOfAbstracMethod();  

তো কথা হল যে মেথডের বডিই নাই সেই মেথডের লেখারই কি দরকার? আমাদের সেই বিখ্যাত Animal এবং Human ক্লাসের উদাহরনটায় ফেরত যাই। Animal ক্লাসে লিখেছিলাম Animal রা হাটতে পারে কিন্তু বিষয়টা ক্লিয়ার না। কারন পৃথিবীতে হাজার হাজার প্রাণী আছে সব প্রানীর হাটা ধরন এক না বা সবার পায়ের সংখ্যা সমান না। তার মানে হল এই মেথডটার বডিতে কি লিখতে হবে আমরা নিশ্চিৎ না। যে কারনে আগের পর্বে আমরা একে ওভাররাইড করে ফেলছিলাম। যেহেতু একটা মেথডের বডি সম্পর্কে আমরা নিশ্চিৎ না সেহেতু তার বডি লিখে সময় নষ্ট করার দরকার আছে? বেটার আমরা ঐ মেথডটার বডি Unimplemented রেখে দিবো।  কোন মেথড আন ইমপ্লিমেন্টেড করতে হলে তার আগে Abstract লিখতে হয়। আর কোন ক্লাসে যদি অন্তত একটা অ্যাবস্ট্রেক্ট মেথড থাকে তাহলে সেই ক্লাসকেও অ্যাবস্ট্রেক্ট করতে হয়। তো আমরা আগের উদাহরনটা এখানে ইমপ্লিমেন্ট করি-

 public abstract class Animal {  
      public abstract void Walk();  
      public void Call()  
      {  
           System.out.println(" Can call");  
      }       
 }  
 public class Human extends Animal {  
      public void Walk()  
      {  
           System.out.println("Human walk using two legs");  
      }  
 }  
 public class MainClass{  
      public static void main(String[] args) {  
           Human human1 = new Human();  
           human1.Walk();  
      }  
 }  
 OUTPUT  
 Human walk using two legs  


কিছু বিষয়- 
১। অ্যাবস্ট্র্যাক্ট ক্লাসের কোন অবজেক্ট তৈরী করা যায়না কারন অ্যাবস্ট্র্যাক্ট ক্লাসের আন ইমপ্লিমেন্টেড মেথড থাকে
২। যখন কোন ক্লাসে নির্দিষ্ট একটা মেথড অবশ্যই থাকা উচিৎ বলে মনে করা হয় কিন্তু ভেতরে কি লিখতে হবে তা নিশ্চিৎ শুধু সে ক্ষেত্রেই অ্যাবস্ট্রেক্টেড মেথড ইউজ করা হয়।
৩। অ্যাবস্ট্রেক্ট ক্লাসকে যারা ইনহেরিট করবে তাদেরকে অবশ্যই অ্যাবস্ট্র্যাক্ট মেথড ইমপ্লিমেন্ট করতে হবে। নাহলে কম্পাইলার এরর দিবে। যদি না করা হয় তাহলে ইনহেরিটেড ক্লাসকেও অ্যাবস্ট্রেক্ট করে দিতে হবে। মানে আজ হোক কাল হোক অবজেক্ট তৈরী করতে হলে ইমপ্লিমেন্ট করা লাগবেই :P
৪। অ্যাবস্ট্র্যাক্ট ক্লাসে একই সাথে অ্যাবস্ট্রেক্ট মেথড এবং কনক্রেট মেথড( ইমপ্লিমেন্টেড) থাকতে পারে।

অবজেক্ট অরিয়েন্টেড প্রোগ্রামিং - ৫ঃ পলিমরফিজম

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

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

যেমন ধরো,আমাদের যোগ করা দরকার। আমার কখনো ২ নাম্বার যোগ করার দরকার পড়ে, কখনো ৩ টা আবার কখনো ৪ টা। এই কাজটি আমরা মেথড দিয়ে করতে চাই।  আমরা জানি মানুষ চিন্তা করতে পারে।  তার মানে মানুষ যোগ করতে পারে। তাহলে আগের পর্বের মানুষের যে Think() নামক মেথডটা লিখছিলাম সেটা দিয়েই কাজটা সারতে পারি। দেখো কাজটা আমরা কিভাবে করি :P
 public class Human extends Animal {  
      double sum;  
      public void think()  
      {    
           System.out.println("Wanna see that I can think?")
           System.out.println("Give me some number and see I can do sum");  
      }  
      public void think(double a , double b)  
      {  
           sum = a+b;  
           System.out.println(sum);  
      }  
      public void think(double a , double b, double c)  
      {  
           sum = a+b+c;  
           System.out.println(sum);  
      }  
      public void think(double a , double b, double c, double d)  
      {  
           sum = a+b+c+d;  
           System.out.println(sum);  
      }  
 }  
 public class StartUp {  
      public static void main(String[] args) {  
           Human human1 = new Human();  
           human1.think();  
           human1.think(30,40);  
           human1.think(30,40,50);  
           human1.think(50,60,70,80);  
      }  
 }  
সবগুলো মেথডের নামই সেইম। তবে তাদের আলাদা আলাদা প্যারামিটার। কোন মেথডটা কল হবে তা নির্ভর করে ৩ টা জিনিসের উপর-
১। মোট প্যারামিটার সংখ্যা ।
২। প্যারামিটারের ডাটা টাইপ।
৩। ডাটা টাইপের সিকুয়েন্স।
এই তিনটা জিনিস যে মেথডের সাথে মিলবে সেই মেথডটাই কল হবে।

 OUTPUT
 Wanna see that, I can calculate?  
 Give some number and see I can add  
 70.0  
 120.0  
 260.0  

উপরে আমি যদি মেইন ফাংশ থেকে জিরো প্যারামিটার কল করি তাহলে প্রথম মেথডটা কল হবে, আবার ৪ টা ডাবল টাইপ প্যারামিটার দিয়ে কল করি তাহলে শেষেরটা কল হবে। তবে অন্য কোন ডাটা টাইপ দিয়ে কল করলে কোনটাই কল হবেনা। আশা করি বুঝতে সমস্যা হচ্ছেনা।

ওভাররাইডিংঃ 


উপরে দেখা যাচ্ছে, Animal ক্লাসকে Human এবং Dog ক্লাস Inherit করেছে।  Animal ক্লাসের ভিতর Walk এবং Call মেথড লিখা আছে। কিন্তু একটা সময় পর তোমার মনে হল Animal ক্লাসের মেথডটি Human বা Dog ক্লাসের জন্য পর্যাপ্ত না অথবা সাবক্লাস দুটোতে সেটার সংশোধন করা দরকার সেক্ষেত্রে তুমি সেই মেথডটাই সাবক্লাসে লিখে দিবে। তখন সাবক্লাসের জন্য Animal ক্লাসের মেথডটা আর কাজ করবেনা; যেটা সাবক্লাসে লিখে দিয়েছো সেটাই কাজ করবে। মানে হল প্যারেন্ট ক্লাসের একটা মেথড সাবক্লাস দিয়ে ওভাররাইড হয়ে গেছে। আবার তুমি যদি মেইন ক্লাসের অবজেক্ট দিয়ে কল তাহলে আবার মেইন ক্লাসেরটাই কাজ করবে।  যেহেতু কোন মেথডটা কখন কল হয় তা রানটাইমে নির্ধারন হয় সেহেতু একে রানটাইম পলিমরফিজম বা ডায়নামিক পলিমফিজম বলা হয়।

 public class Animal {  
      public String name;  
      public int age;  
      public void Walk()  
      {     
           System.out.println("This message is from base class: ")
           System.out.println("Can Walk");  
      }  
      public void Call()  
      {  
           System.out.println(" Can call");  
      }       
 }  
 public class Human extends Animal {  
      public void Walk()  
      {  
           System.out.println("This message is from sub class:");  
           System.out.println("Human walks using two legs");  
      }  
 }  
 public class MainClass{  
      public static void main(String[] args) {  
           Human human1 = new Human();  
           human1.Walk();  //Walk() will be called on Human class. 
          
          Animal animal1 = new Animal();
          animal1.Walk();  //Walk will be called on Animal class 
      }  
 }  
 OUTPUT  
 This message is from sub class:  
 Human walks using two legs  

This message is from base class:
Can Walk


অবজেক্ট অরিয়েন্টেড প্রোগ্রামিং - ৪ঃ ইনহেরিটেন্স

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

এই দুটো ক্লাস লিখতে হলে আমাদের মোট ৪ টা ভেরিয়েবল এবং ৫ টা মেথড লিখতে হবে। কিন্তু যদি একইভাবে আমাদের ১০০০ টা প্রাণী নিয়ে লিখতে হয় তাহলে আমাদের টোটাল ভেরিয়েবল এবং মেথডের সংখ্যা কত হবে জানো? টোটাল ভেরিয়েবল হবে ৪০০০০ এবং টোটাল মেথড হবে ৫০০০। জীবন শেষ! আর ক্লাসের ভিতর আরো বেশী কিছু লিখার দরকার হবে তাতে তো কোন কথাই নাই। কোডিং না করে পালানো লাগবে! তবে আমরা চাইলে এই সংখ্যাটা অনেক কমিয়ে আনতে পারি।

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


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


আমরা জানি সকল প্রানীরই name এবং age থাকে। আবার প্রানীই হাটতে এবং ডাকতে পারে। তাই ওই ক্লাসের নাম দিলাম Animal. তুমি চাইলে যেকোন মিনিংফুল নাম দিতে পারো। 
উপরে দেখা যাচ্ছে Human এবং Dog ক্লাস Animal ক্লাসকে Inherit করছেএর ফলে Animal ক্লাসে যা আছে তা Human এবং Dog ক্লাসে চলে আসছে। তাহলে আমাদের আর রিপিট এলিমেন্ট গুলো আর লিখতে হচ্ছেনা। এখানে আমরা ৯ টা এলিমেন্ট এর পরিবর্তে ৬ টা লিখে কাজ সেরে ফেলছি। ১০০০ এর জন্য এখন কয়টা লিখতে হচ্ছে জানো ?  ২ টা ভেরিয়েবল এবং ৩টা মেথড!! এভাবে আমরা কোড রিপিটেশন থেকে মুক্তি পেতে পারি এবং অনেক অনেক সময় বেঁচে যায়।
একটা ক্লাসকে ইনহেরিট করার জন্য জাভাতে extends নামের দারুন এক অপারেটর আছে। যা দিয়ে একটা ক্লাসকে অন্য ক্লাস থেকে ইনহেরিট করা যায়। আমরা উপরের কাজটিই জাভা দিয়ে লিখবো-
 public class Animal {  
      public String name;  
      public int age;  
      public void Walk()  
      {  
           System.out.println(name+ " Can walk");  
      }  
      public void Call()  
      {  
           System.out.println(name+ " Can Call");  
      }       
 }  
 public class Human extends Animal {  
      public void think()  
      {  
           System.out.println(name+ "Can think");  
      }  
 }  
 public class Dog extends Animal {  
 }  
 public class MainClass{  
      public static void main(String[] args) {  
            
           //creating humans object
           Human human1 = new Human();  
           human1.name = "Rakib";  
           human1.age = 23;  
           
           //creating dogs object
           Dog dog1 = new Dog();  
           dog1.name = "John";  
           dog1.age = 2;  
          
           //showing humans information
           System.out.println(human1.name+ " is "+ human1.age+ " Years Old");  
           human1.Walk();  
           
           //showing dogs information
           System.out.println(dog1.name+ " is "+ dog1.age+ " Years Old");
           dog1.Walk();  
      }  
 }  
 OUTPUT  
 Rakib is 23 Years Old  
 John is 2 Years Old  
 Rakib Can Walk  
 John Can Walk  
Extends - এটা হল জাভার একটি অপারেটর, যার সাহায্যে এক ক্লাসের পাবলিক এলিমেন্ট অন্য ক্লাসে ইনহেরিট করানো হয়।
Practice:
1. Do the above task using encaptulation and constructor

অবজেক্ট অরিয়েন্টেড প্রোগ্রামিং - ৩ঃ কনস্ট্রাক্টর



কোন কিছু Initilize করার জন্য বার বার setName, setAge কল করতে হচ্ছে। এরকম যদি ১০০ টা ভেরিয়েবল ইনিসিয়ালিজ করার দরকার পড়ে তাহলে কি তুমি বার বার set মেথড লিখবা? কখনোই না বরং এটা অনেক সময় সাপেক্ষও বটে! সেক্ষেত্রে আমাদের এমন কিছু একটার প্রয়োজন যেটায় অব্জেক্ট ক্রিয়েট করার সাথে সাথেই এগুলো বা মেন্ডেটরি জিনিসগুলো Initilize করে দিবে। সেজন্য আমরা Human ক্লাসের ভেতরেই একটা কনস্ট্রাক্টর লিখে দিবো-

কনস্ট্রাক্টরের বৈশিষ্ট্যঃ কনস্ট্রাক্টর অনেকটা ফাংশনের মত। তবে এর কোন রিটার্ন টাইপ থাকেনা এবং এর নাম ঐ ক্লাসের নাম অনুযায়ী হয়ে থাকে। নীচের প্রোগ্রামটি লক্ষ্য করিঃ

 public class Human {  
      private String name;  
      private int age;  
      public Human(String Name, int Age)  
      {  
           name = Name;  
           age = Age;  
      }  
 }  

মেইন ফাংশন থেকে এখন এইটুকু করে দিলেই কাজ শেষ-
 public class StartUp {  
      public static void main(String[] args) {  
           Human aHuman = new Human("Rakib", 23);  //creating object  
      }  
 }  

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

ডিফল্ট কন্সট্রাক্টরঃ আমরা যদি কোন কনস্ট্রাক্টর তৈরী না করি তাহলে সিস্টেম ডিফল কন্সট্রাক্টর ইউজ করে। ডিফল্ট কন্সট্রাক্টর হচ্ছে এরকম-

 public Human()  
      {  
      }  

new অপারেটরঃ এটা একটি জাভা অপারেটর। এই অপারেটরের সাহায্যেই কন্সট্রাক্টর অব্জেক্ট তৈরী করে। এটা দ্বারা কম্পাইলারকে বুঝানো হয় যে আমরা নতুন একটি অব্জকেট ক্রিয়েট করতে চাচ্ছি।