জাভাঃ String ক্লাসের গল্প

জাভা String ক্লাস বোধহয় জাভার বহূল ব্যাবহৃত ক্লাস।  প্রোগ্রামের চিপা-চাপা প্রায় সব জায়গাতে আপনি এই ভদ্রলোককে খুজে পাবেন। চিন্তা করুন, প্রোগ্রামে যত বার String ব্যাবহার করেছেন আপনার মাথায় ততগুলো চুল আছে?

String ক্লাস হচ্ছে জাভার java.lang প্যাকেজের সদস্য। এই ক্লাস "ক্যারেক্টার স্ট্রিং" কে রিপ্রেজেন্ট করে।

কিভাবে String ক্লাসের অবজেক্ট বানাব?

String যেহেতু ক্লাস। যত গুলো স্ট্রিং আপনি প্রোগ্রামে ডিক্লেয়ার করেন তারা এই ক্লাসের অবজেক্ট। যেমন এখানে ("letters" , "the quick brown") দুইটি String ক্লাসের অবজেক্ট আছে।

আমরা new অপারেটর ব্যাবহারের মাধ্যমে, এ্যাসাইনমেন্ট অপারেটরের(=) মাধ্যমে বা কোটেশনের ("") মাধ্যমে String ডিক্লেয়ার করতে পারি। যেমনঃ

String str1 = new String("good boy");
String str2 = "bad boy";
System.out.println("Hello world!");
আপনি overloaded কনস্টাক্টরের মাধ্যমেও String ডিক্লেয়ার করতে পারেন। যেমনঃ
String str1 = new String( "John Snow" );
char[] name = new char[]{ 'J', 'o', 'h', 'n', ' ', 'S', 'n', 'o', 'w' };
String lordCommander = new String( name );
(String কনস্ট্রাক্টর,  যেটি Character Array কে প্যারামিটার হিসেবে নেয়)
StringBuilder sb = new StringBuilder( "String Builder" );
String str1 = new String( sb );
(String কনস্ট্রাক্টর,  যেটি StringBuilder অবজেক্ট কে প্যারামিটার হিসেবে নেয়)
StringBuffer  sbf = new StringBuffer( "String Buffer" );
String str2= new String( sbf );
(String কনস্ট্রাক্টর,  যেটি StringBuffer অবজেক্ট কে প্যারামিটার হিসেবে নেয়)

String ক্লাস immutable?
হ্যাঁ String ক্লাস immutable। এটি মনে রাখার মত একটি পয়েন্ট। ভূলবেন না কিন্তু। immutable বলতে বুঝায় একবার অবজেক্ট তৈরী হয়ে যাওয়ার পর এর কন্টেন্ট কোনো ভাবে পরিবর্তন করা যাবে না। যেমনঃ
String str1= "winter is coming";
অবজেক্ট str1 এর কন্টেন্ট "winter is coming" এর কোনো একটি ক্যারেক্টার কোনো ভাবেই replace/remove কোনো কিছুই করা যাবে না, কোনো modification সম্ভব না।

আপনি বলতে পারেন String ক্লাসের তো replace(), concat(), remove(), toUpper(), toLower() ইত্যাদি ইত্যাদি মেথড আছে।  এগুলো স্ট্রিং অবজেক্টের কন্টেন্টকে modify করে না, তারা আপনার স্ট্রিং অবজেক্ট থেকে নতুন একটি অবজেক্ট বানায় এবং সেটি রিটার্ণ করে।
String  s1= "hello world";
String s2 = s1.replace( "world", "WORLD" );
System.out.println( s1 );  // this will print hello world
System.out.println( s1 );  // this will print hello WORLD
এখানে ছবিতে String ক্লাসের মেথড গুলোকে বিভিন্ন ক্যাটাগরিতে ভাগ করা হয়েছে যাতে আপনি আরো ভাবে মেথডগুলোর অপারেশন বুঝতে পারেন।

charAt():
আপনি charAt(int index) এই মেথডের মধ্যমে index পজিশনের ক্যারেকক্টার
retrive করতে পাববেন। যেমনঃ
String name = new String( "John Poul" );
System.out.println( name.charAt( 0 ) );
জিরো(0) পজিশনে ক্যারেক্টার আছে J, এই স্টেটমেন্ট সেটি প্রিন্ট করবে। একইভাবে নীচের স্টেটমেন্ট u প্রিন্ট করবেঃ
System.out.println( name.charAt(7) )
কারণ 7 ইনডেক্সে আছে u

substring():
substring() মেথড দুই ধরনের কাজ করতে পারে। প্রথমটি হচ্ছে আপনি একটি পজিশন উল্লেখ করে দিলেন। substring() মেথড ঐ পজিশন থেকে String এর শেষ পর্যন্ত নিয়ে একটি String রিটার্ণ করবে।

আরেকটি হচ্ছে আপনি শুরুর এবং শেষের পজিশন উল্লেখ করে দিলেন, substring() মেথড শুরুর index এর character থেকে শেষের index এর আগ পর্যন্ত String রিটার্ণ করবে। যেমনঃ
String exam = "Oracle";
String sub = exam.substring( 2 );
System.out.println( sub ); // this will print acle
String exam = "Oracle";
String result = exam.substring( 2, 4 );
System.out.println( result ); // this will print ac
মনে রাখবেন দ্বিতীয় ক্ষেত্রে ২য় প্যারামিটারের আগের index এর ক্যারেক্টার পর্যন্ত নিয়ে Sub String রিটার্ণ করবে।

trim():
trim() মেথড String এর আগের ও পরের স্পেস remove করে বাকী String রিটার্ণ করবে। যেমনঃ
String var = "   john denver   ";
System.out.print( ":" )
System.out.print( var ) ;
System.out.print( ":" )
আউটপুট হবে :   john denver   :

আমরা যদি trim() মেথড এ্যাপ্লাই করি
String var = "   john denver   ";
System.out.print( ":" )
System.out.print( var.trim() ) ;
System.out.print( ":" )
আউটপুট হবে :john denver: 

replace():
এই মেথড কোনো String থেকে কোনো একটি ক্যারেক্টারকে অন্য একটি ক্যারেক্টার দিয়ে replace করে String টি রিটার্ণ করবে। ক্যারেক্টারের পরিবর্তে "সিকুয়েন্স অফ ক্যারেক্টার" কে আরেকটি "সিকুয়েন্স অফ ক্যারেক্টার" replace করবে।যেমনঃ
String word = "INTANGIBLE";
System.out.println( word.replace('G', 'g') ); //this will print INTANgIBLE
System.out.println( word.replace('TANG', 'tang') ); // this will print INtangIBLE
মনে রাখবেন প্যারামিটার দুটি হয় ক্যারেক্টার অথবা "সিকুয়েন্স অফ ক্যারেক্টার" হতে হবে। দুটি দুই রকমের হলে কম্পাইল হবে না। যেমন নীচের দুটি প্রিন্ট স্টেটমেন্ট কম্পাইল হবে না।
String letters = "ABCBA";
System.out.println(letters. replace('B', "b") );
System.out.println( letters.replace("B", 'b') );
আরেকবার বলছি মেথড নতুন একটি String রিটার্ণ করছে, আমাদের আগের String আগের মতই আছে। যেমনঃ
System.out.println( letters );
এটি ABCBA প্রিন্ট করবে।

length() :
lenght() মেথড String এর দৈর্ঘ্য রিটার্ণ করবে। String এর দৈর্ঘ্য তার শেষ index নাম্বারের চেয়ে ১ বেশি হয়। যেমনঃ
System.out.println("ali ashik".length() );
এটি 9 প্রিন্ট করবে।

startsWith() এবং endsWith():
startsWith() মেথড চেক করে একটি String একটি নির্দিষ্ট prefix দিয়ে শুরু হয় কিনা? যদি শুরু হয় তাহলে এটি true রিটার্ণ  করবে, নইলে false রিটার্ণ করবে। prefix টি আপনি প্যারামিটারে প্রোভাইড করে দিবেন।

মনে রাখবেন এই চেকিং শুরু হবে জিরো (0) index থেকে। আপনি ইচ্ছা করলে চেকিং কোন index থেকে শুরু হবে সেটি নির্দিষ্ট করে দিতে পারেন। যেমনঃ
String letters = "ABCAB";
System.out.println(letters.startsWith("AB")); // this will print true
System.out.println(letters.startsWith("a")); // this will print false 
System.out.println(letters.startsWith("A", 3) ); // cheching form index 3 
endsWith() মেথড চেক করে একটি String একটি নির্দিষ্ট suffix দিয়ে শেষ হয় কিনা? যদি শেষ হয় তাহলে এটি true রিটার্ণ  করবে, নইলে false রিটার্ণ করবে। যেমনঃ
String letters = "ABCAB"
System.out.println( letters.endsWith("CAB") );
System.out.println( letters.endsWith("B") );
System.out.println( letters.endsWith("b", 3) );
একটু খেয়াল করে, startsWith() এবং endsWith() এ প্যারামিটার সবসময় String কিন্তু Character না।

আজকে এই পর্যন্ত। বিদায়, টাটা। আপনাদের জন্য দুইটা কাজ রেখেছি। নীচে দেখুন।

কাজ-১ঃ
নীচের কোড দেখি। এটাকে বলা হয় method chainingExecution বাম থেকে শুরু হয় ডানে যাবে।
আউটপুট কি?
String result = "Sunday   ".replace( ' ', 'z' ).trim().concat( "M n" );
কাজ-২ঃ
নীচের কোডের জন্য কোনটি সঠিক?
String letters = "ABCAB";
System.out.println( letters.substring(0,2) ).startsWith( 'A' );
(a) true(b) false
(c) AB(d) ABC
(e) Compilation error
 class MyClass{
}

জাভাঃ জাভার বর্নমালা | Encapsulation ও Access Modifier

Encapsulation কিঃ
সোজা কথায় Encapsulation হচ্ছে কোন কিছুকে ক্যাপসুলের ভিতরে আবদ্ধ করে তাকে রক্ষা করা। ধরুন আপনি বিশ্ববিদ্যালয়ের হলে থাকেন, আপনার জাম্বো সাইজের "টুথপেস্ট" পুরো হলের জনগণের কাছে সরকারি সম্পত্তি। প্রতি ১৫ দিনে নতুন টুথপেস্ট কেনার হাত থেকে বাঁচার জন্য বাজার থেকে লোহার একটা খাঁচা এনে আপনার মহামূল্যবান জিনিসগুলোকে ঐ খাঁচায় (টুথপেস্ট সহ) রেখে তালা মেরে দিলেন। তাহলে আপনার টুথপেস্ট Encapsulated গেল এখন আসুন জাভাতে Encapsulation কি এবং কেন? ওকে উপরের এনালজির সাথে মিলিয়ে দেখি। আপনি কোড করছেন সে কোডকে আপনি সরকারি সম্পত্তি হতে দিতে চান না। এ জন্য আপনি কোন একটি টেকনিক ব্যাবহার করে আপনার কোডকে তালাবদ্ধ করে রাখলেন বাহিরের জগৎ থেকে। তাহলে জাভাতে আমরা কি টেকনিক ব্যাবহার করতে পারি? জাভাতে Encapsulation এর জন্য ত্রাণকর্তার রূপে সামনে এসেছে Access Modifier

Access Modifier এর গোমর ফাঁসঃ
উপরের আলোচনা থেকে এতক্ষনে ধারনা করে ফেলেছেন, Access Modifier কোনো ক্লাসের কোডকে অন্য কোনো ক্লাস যেন ব্যাবহার/এক্সেস করতে না পারে সেটি দেখে। এর প্রয়োজনীতা কি? ধরুন "কাশেম ব্যাংক" একটি সফটওয়্যার আপনি বানিয়েছেন। এখন অন্যকেউ যদি এই সফটওয়্যার এর Account ক্লাসের balance মেম্বার(Instance variable) কে এক্সেস করতে পারে, তাহলে কি হবে ভেবে দেখেছেন?
class Account{
    private double balance;
    ..................
}

আমরা Account ক্লাসের balance নামের Instance variable কে Private Access যুক্ত করে দিয়েছি তাই Account ক্লাসের বাহিরে অন্য কোনো ক্লাস একে এক্সেস করতে পারবে না। "সো নো হাঙ্কি পাঙ্কি উইথ মাই এ্যাকাউন্ট"।

Access Modifier কয় ধরনের আছে?
জাভা পৃথিবীতে Access Modifier আছে চার ধরনের-
  • public 
  • protected 
  • default 
  • private 

ক্লাসের মেম্বার চারটি Access Modifier যুক্ত হতে পারলেও ক্লাসের নিজের সাথে শুধুমাত্র দুইটি Access Modifier যুক্ত হয় এটিই শেষ না। যখন কোনো ক্লাসে বা ক্লাসের মেম্বারের সাথে কোনো Access Modifier যুক্ত না থাকে তখন সেটি default এক্সেস যুক্ত। default ছাড়া অন্য Access Modifier যুক্ত হতে হলে অবশ্যই তাদের সাথে সংশ্লিষ্ট কিওয়ার্ড থাকতে হবে। নিচের কোডে দেখি-

class Poo
{
   private int a;
   private int b;
   protected int c;
   int d;
}

দেখুন উপরের ক্লাস Poo তে "d" মেম্বারটি default এক্সেস যুক্ত। অন্যগুলোর এক্সেস কি আমরা কিওয়ার্ড থেকে দেখতে পাচ্ছি।

সিতা কার বাপ? এক্সেস করতে পারে এই কথার মানে কি
আমরা জানি Rahim দের ঘরে Karim এর এক্সেস/প্রবেশাধিকার থাকলে তিনি Rahim দের ঘরে কি কি আছে তা দেখতে পারবেন এবং কোনো একটা জিনিস ব্যাবহার করতেও পারবেন। যার Rahim দের ঘরে এক্সেস নেই তার ধরে দেখা তো দূরের থাক ঘরে ঢুকাও অসম্ভব। একইভাবে ক্লাস A যদি ক্লাস B কে এক্সেস করতে পারে তাহলে B এর মেম্বার(ঘরের জিনিসপাতি) ক্লাস A এর কাছে ভিজিবল/দর্শনীয়।

যখন কোনো ক্লাস অন্য ক্লাস বা তার মেম্বারকে এক্সেস করার সুযোগ নেই কিন্তু এক্সেস করার চেষ্টা করে তাহলে কি হবে? কম্পাইলার কানের নিচে একটা দিয়ে বলবে, নে বাবা "একটা কম্পাইলেশন এরর" খা।

কোনো ক্লাসের মেম্বার গুলোকে দু ভাবে অন্য ক্লাস থেকে এক্সেস করা হয়-

  • এক ক্লাসের কোড অন্য ক্লাসের মেম্বারকে অবজেক্টের রেফারেন্স দিয়ে ডট(.) অপারেটরের মাধ্যমেএক্সেস করে। 
  • কোনো সাব ক্লাস এর সুপার ক্লাসের কোনো মেম্বারকে Inherit করার মাধ্যমে এক্সেস করে।
প্রথম ধরনের এক্সেস ঘটে আমরা বলেছি, যখন কোনো ক্লাসের মেথডের ভিতরে আরেকটি ক্লাসের মেম্বারকে ডট অপারেটর (.) এর মাধ্যমে এক্সেস করা হয়। নিচের কোড দেখি-

class Hospital{
   public String Descripton(){
      return "good";
   }
}
class People{ 
   public void Investigate(){ 
      Hospital h = new Hospital(); 
      System.out.println( h.Descripton() ); 
   } 
} 

(Inheritance এখনো পর্যন্ত যাদের মাথার উপর দিয়ে যায় তারা এই অংশটি স্কিপ করতে পারেন, আগের Inheritance শিখে নিন)

কোনো সাব ক্লাস এর সুপার ক্লাসের কোনো মেম্বারকে Inherit করার মাধ্যমে ঐ মেম্বারকে নিজস্ব সম্পত্তি মনে করে। যেমন নিচের CorruptOfficial ক্লাসের Spend() মেথড People ক্লাসের মেম্বার money কে নিজের মত করে ব্যাবহার করেছে, যেমনটা তার নিজের মেম্বার ownMember কে ব্যবহার করেছে। যেন money, CorruptOfficial ক্লাসের মধ্যে ডিক্লেয়ার করা হয়েছে।

class People{ 
   public int money; 
}
class CorruptOfficial extends People{
   int ownMember = 400; 
   public void Spend(){ 
      System.out.println(money); 
      System.out.println(ownMember); 
   } 
} 

তাহলে সাব-ক্লাস(sub class) কোন কোন মেম্বারগুলোকে নিজের মনে করে এক্সেস করতে পারবে? এটি কিভাবে ঠিক করে দেওয়া হয়? মেম্বারের আগে Access Modifier দিয়ে এটি ঠিক করে দেওয়া হয়।

এখানে আরেকটি কথা মনে রাখুন যদি একটি ক্লাস অন্য আরেকটি ক্লাসকে এক্সেস করতে না পারে, তাহলে সেটার মেম্বারকে কোনো ভাবেই এক্সেস করতে পারবে না। বিষয়টি অনেকটি এইরকম, আপনি ঘরে ঢুকতে না পারলে সোফায় বসবেন কিভাবে? কোনো ক্লাসকে যদি এক্সেস করা যায় কেবল মাত্র তখন ঐ ক্লাসের মেম্বারকে এক্সেস করা যাবে।

তাহলে কোনো ক্লাস অন্য কোনো ক্লাসের মেম্বারতে এক্সেস করতে চাইলে আমরা আমরা সব ক্ষেত্রে ২ টি প্রশ্ন করব- 

  • যে ক্লাসের মেম্বারকে এক্সেস করতে চাই, ঐ ক্লাসকে এক্সেস করা যায় কিনা? 
  • মেম্বারটিকে এক্সেস করা যায় কিনা? 

Public এক্সেসঃ
public এর কথা বলতে হলে সবার আগে বলতে হয়, এটি সরকারি মাল। public কিওয়ার্ড যুক্ত করে একে সরকারি করে দেওয়া হয়েছে। যে কোনো ক্লাসের যে কোনো কোড, একটি ক্লাসের public মেম্বার গুলোকে এক্সেস করতে পারে। কেউ রাগ করে না, এমনকি public হওয়ায় কম্পাইলারও কিছু বলে না। 

যাই হোক এখন থেকে "মাইর কম আওয়াজ বেশী"। নীচে দেখুন Poo নামের একটি ক্লাস আছে -

package pagcage1;
public class Poo{
   public int age;
      public int getAge(){
      return age;
   }
}

অবজেক্ট রেফারেন্স দিয়ে ডট (.) অপারেটরের মাধ্যমে আরেকটি ক্লাস Moo, Poo ক্লাসের মেম্বারগুলোকে এক্সেস করতে পারবে কিনা? উত্তর হচ্ছে হ্যাঁ পারবে । এই ক্ষেত্রে প্রথম দেখতে হবে, ক্লাস Moo, ক্লাস Poo কে এক্সেস করতে পারে কিনা? ক্লাস Poo, public এক্সেস যুক্ত হওয়ার কারণে এটি যে প্যাকেজে থাকুক না কেন ক্লাস Moo একে এক্সেস করতে পারবে।

package package2;
class Moo{
   public void Check(){
      Poo refVar = new Poo();
      refVar.age = 20;
      System.out.println( refVar.getAge() );
   }
}

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

কিন্তু আমাদের ক্লাস Poo যদি public না হয়ে default এক্সেস যুক্ত হয়? সেক্ষেত্রে ক্লাস Moo এবং ক্লাস Poo একই প্যাকেজ ভুক্ত হলে কোনো সমস্যা হবে না কিন্তু এদের প্যাকেজ যদি আলাদা হয়, ক্লাস Moo, ক্লাস Poo কে খুজে পাবে না। ক্লাসকে খুজেই যদি না পেল তাহলে তার public মেম্বারকে কিভাবে এক্সেস করবে? নীচের ক্ষেত্রে এরর দেখাবে -

package pagcage1; 
class Poo{ 
   public int age; 
   public int getAge()
   { 
      return age; 
   } 
}
package package2; 
import package1; 
class Moo{ 
   public void Check()
   { 
      Poo refVar = new Poo(); 
      refVar.age = 20; System.out.println( refVar.getAge() ); 
   } 
} 

এখন আমরা দেখব ক্লাস Moo যদি ক্লাস Poo কে Inherit করে তাহলে ক্লাস Poo এর public মেম্বারগুলোকে এক্সেস করতে পারে কিনা। আগের মত, ক্লাস Poo ডিফল্ট (default) এক্সেস যুক্ত হলে এবং ক্লাস দুটো ভিন্ন প্যাকেজে থাকলে, ক্লাস Moo একে খুজে পাবে না। তাই ক্লাস Poo এর পাবলিক (public) মেম্বারগুলোকে নিজের মনে করা "আনপসিবল"। একই প্যাকেজে থাকলে কোনো সমস্যা নেই। আবার ক্লাস Poo পাবলিক (public) এক্সেস যুক্ত হলে এটি যে প্যাকেজে হোক না কেন, কোনো সমস্যা হবে না।

package pagcage1; 
class Poo{ 
   public int age; 
   public int getAge(){ 
      return age; 
   } 
} 
package package2; 
import package1.Poo; 
class Moo extens Poo{ 
   public void Check(){
      age = 85; // error 
   } 
}
উপরের ক্ষেত্রে এরর দেখাবে কারণ ক্লাস Poo ডিফল্ট(Default) এক্সেস যুক্ত। নিচের ক্ষেত্রে এরর দেখাবে না কারণ ভিন্ন প্যাকেজে হলেও ক্লাস Poo পাবলিক (public) এক্সেস যুক্ত।

package pagcage1; 
public class Poo{
   public int age; 
   public int getAge(){ 
      return age;
   } 
} 
package package2; 
import package1.Poo; 
class Moo extens Poo{ 
   public void Check(){
      age = 85; 
   } 
}

তাহলে উপরের আলোচনার সারাংশ হচ্ছে, কোনো ক্লাস যখন (default) এক্সেস যুক্ত হয় তখন শুধুমাত্র একই প্যাকেজের অন্য ক্লাস থেকে ঐ ক্লাসের পাবলিক (public) মেম্বারগুলোকে এক্সেস করা যাবে। ভিন্ন প্যাকেজের অন্য ক্লাস থেকে এক্সেস করা যাবে না। 

private এক্সেসঃ 
private হচ্ছে সবচেয়ে বেশি ঘাউরা। যখন কোনও ক্লাসের private মেম্বার ঐ ক্লাস ভিন্ন অন্য যে কোনো ক্লাসের মেথড এদের এক্সেস করতে পারবে না। যেমন ধরুন আপনার বেডরুমের সবকিছুই প্রাইভেট এমনকি "হোয়াইট হাউজ" বা "বঙ্গভবন" এর কোনো বাসিন্দার সেখানে নাক গলানোর সুযোগ নেই। তাহলে কোনো ক্লাস একই প্যাকেজ এ থাকুক বা ভিন্ন প্যাকেজে থাকুক অন্য ক্লাস থেকে একে ডট(.) অপারেটরের মাধ্যমে এক্সেস করা যাবে না।  

package pagcage1; 
public class Poo{ 
   private int numOfLove; 
} 
package package2; 
import Poo; 
class MasterShifu{
   public void Check(){
      Poo refVar = new Poo();
      refVar.numOfLove = 100; 
   } 
}

আমরা প্রথমে দেখব ক্লাস Poo কে ক্লাস MasterShifu এক্সেস করতে পারে কিনা। এরা ভিন্ন প্যাকেজে হলেও ক্লাস Poo পাবলিক(public) এক্সেস যুক্ত হওয়ায় যে কোনো প্যাকেজের যে কোনো ক্লাস একে এক্সেস করতে পারবে। কিন্তু ক্লাস Poo ডিফল্ট(default) এক্সেস যুক্ত হলে ভিন্ন প্যাকেজের কোনো ক্লাস একে এক্সেস করতে পারবে না। 

এখানে ক্লাস MasterShifu এর মেথড Check(), ক্লাস Poo এর মেম্বার(Instance Variable) numOfLove কে ডট(.) অপারেটরের মাধ্যমে এক্সেস করতে চাইলে এরর দেখাবে কারণ numOfLove এর Access modifier হচ্ছে private। ক্লাস Poo এবং ক্লাস MasterShifu একই প্যাকেজে হলেও একই ঘটনা ঘটত। private এক্সেস যুক্ত হওয়ায় ক্লাস MasterShifu ক্লাস Poo এর numOfLove নামে নামে কোনো Instance variable আছে সেটিও জানতে পারবে না। 

Inheritance এর মাধ্যমে এক্সেস করতে পারবে কিনা? উত্তর হচ্ছে না, পারবে না। যে প্যাকেজে ক্লাস গুলো থাকুক না কেন, কখনো Inheritance এর মাধ্যমে কোনো ক্লাসের private মেম্বারকে এক্সেস করা যায় না। নীচের কোড গুলো দেখি। এখানে ক্লাস MasterShifu থেকে ক্লাস Poo কে Inherit করে এর প্রাইভেট(private) মেম্বারকে এক্সেস করার চেষ্টা করা হয়েছে এবং প্রত্যেক ক্ষেত্রে এরর কম্পাইলার এরর দেখাবে।

package pagcage1; 
public class Poo{ 
   private int numOfLove; 
}
package package1; 
import Poo; 
class MasterShifu extens Poo{
   public void Check(){ 
      numOfLove = 100; 
   } 
} 
A(I): numberOfLove প্রাইভেট, দুই ক্লাস একই প্যাকেজেA(II): ৫ নাম্বার লাইনে এরর দেখাবে
package pagcage1; 
public class Poo{ 
   private int numOfLove; 
}
package package2; 
import Poo; 
class MasterShifu extens Poo{
   public void Check(){
       numOfLove = 100; 
   } 
} 
B(I): numberOfLove প্রাইভেট, দুই ক্লাস আলাদা প্যাকেজেB(II): ৫ নাম্বার লাইনে এরর দেখাবে
package pagcage1; 
class Poo{ 
   private int numOfLove; 
}
package package1; 
import Poo; 
class MasterShifu extens Poo{ 
   public void Check(){
      numOfLove = 100; 
   } 
} 
C(I): Poo ক্লাস defult, দুই ক্লাস একই প্যাকেজেC(II): ৫ নাম্বার লাইনে এরর দেখাবে
package pagcage1; 
class Poo{ 
   private int numOfLove; 
}
package package2; 
import Poo; 
class MasterShifu extens Poo{ 
   public void Check(){ 
      numOfLove = 100; 
   } 
} 
D(I): Poo ক্লাস defult, দুই ক্লাস আলাদা প্যাকেজেD(II): ৩ নাম্বার লাইনে এরর দেখাবে

প্রোটেক্টেড (protected) ও ডিফল্ট (default) এক্সেসঃ 
প্রোটেক্টেড (protected) ও ডিফল্ট (default) এক্সেস মডিফায়ার প্রায় একই রকম। পার্থক্য শুধু এক জায়গায়, কোনো ক্লাসের ডিফল্ট (default) এক্সেস যুক্ত মেম্বারগুলোকে শুধু মাত্র একই প্যাকেজের ক্লাস থেকে এক্সেস করা যাবে। অন্যদিকে কোনো ক্লাসের প্রোটেক্টেড (protected) এক্সেস যুক্ত মেম্বারগুলোকে ভিন্ন প্যাকেজের তার সাবক্লাস (subclass) থেকেও এক্সেস করা যাবে। যেমন নীচের কোডে দেখুন-

Default এক্সেসঃ দুইটি ক্লাস একই প্যাকেজেprotected এক্সেসঃ দুইটি ক্লাস একই প্যাকেজে
package pagcageA; 
public class Poo{ 
   int numOfLove; 
} 

package packageA; 
class MasterShifu extends Poo{
   public void Check(){
      numOfLove = 100; 
   } 
}
package B; 
public class Poo{
   protected int numOfLove; 
}

package packageB; 
class MasterShifu extends Poo{ 
   public void Check(){
      numOfLove = 100; 
   }
} 
একই প্যাকেজের default মেম্বারকে inherit করা যায়, তাই কোনো এরর দেখাবে নাএকই প্যাকেজের protected মেম্বারকেও inherit করা যায়, তাই এখানেও কোনো এরর দেখাবে না

আমি যা বলার বলে দিয়েছি। এবার আপনি চিন্তা করুন দুই ক্ষেত্রে ক্লাস Poo পাবলিক(public) না হয়ে ডিফল্ট(default) এক্সেস যুক্ত হত, তাহলে কি কোনো এরর দেখাত? ডিফল্ট(default) এক্সেস যুক্ত ক্লাস শুধুমাত্র একই প্যাকেজের অন্য ক্লাসের কাছে ভিজিবল, অন্য প্যাকেজের কোনো ক্লাস এদের খুজে পাবে না। এই জন্য ডিফল্ট(default) এক্সেস কে প্যাকেজ এক্সেসও বলা হয়। 

দয়া করে এবার নিচের কোডের দিকে তাকাই-

Default এক্সেসঃ দুইটি ক্লাস ভিন্ন প্যাকেজেprotected এক্সেসঃ দুইটি ক্লাস ভিন্ন প্যাকেজে
package alibaba; 
public class Poo{ 
   int numOfLove; 
} 

package fortyThief; 
class MasterShifu extends Poo{
   public void Check(){
      numOfLove = 100; 
   } 
}
package earth; 
public class Poo{
   protected int numOfLove; 
}

package moon; 
class MasterShifu extends Poo{ 
   public void Check(){
      numOfLove = 100; 
   }
} 
ভিন্ন প্যাকেজের default মেম্বারকে inherit করা যায় না, তাই numOfLove = 100 এর জন্য এরর দেখাবেভিন্ন প্যাকেজের protected মেম্বারকে inherit করা যায়, তাই numOfLove = 100 এর জন্য কোনো এরর দেখাবে না

আগের বার বলে দিলেও এবার বলছি না। এখন বলুন দুই ক্ষেত্রে ক্লাস Poo পাবলিক(public) না হয়ে ডিফল্ট(default) এক্সেস যুক্ত হত, তাহলে কি কোনো এরর দেখাত? 

তাহলে আমরা Inheritance এর ক্ষেত্রে ডিফল্ট(default) এবং প্রোটেক্টেড(protected) এক্সেস এর কি কি ইস্যু থাকতে পারে তা আলোচনা করেছি। এখন আমরা দেখব অবজেক্টের রেফারেন্সের মাধ্যমে কিভাবে ডিফল্ট(default) ও প্রোটেক্টেড(protected) এক্সেস যুক্ত মেম্বারকে কিভাবে এক্সেস করা যায়।

একই প্যাকজের কোনো ক্লাসের ডিফল্ট(default) বা প্রোটেক্টেড(protected) মেম্বারকে ঐ প্যাকেজের আরেকটি ক্লাস থেকে অবজেক্ট রেফারেন্সের দিয়ে ডট(.) অপারেটরের মাধ্যমে এক্সেস করা যাবে। আসুন কোড দেখি-

Default এক্সেসঃ দুইটি ক্লাস একই প্যাকেজেprotected এক্সেসঃ দুইটি ক্লাস একই প্যাকেজে
package com.main.packageA; 
public class Poo{ 
   int numOfLove; 
}

package com.main.packageA; 
class MasterShifu extends Poo { 
   public void Check() { 
      Poo refVar = new Poo(); 
      refVar.numOfLove = 100; 
   } 
}
package com.main.packageB; 
public class Poo{ 
   protected int numOfLove; 
}

package com.main.packageB; 
class MasterShifu extends Poo { 
   public void Check() { 
      Poo refVar = new Poo(); 
      refVar.numOfLove = 100; 
   } 
}
একই প্যাকেজের default মেম্বারকে ডট(.) অপারেটর দিয়ে এক্সেস করা যায়একই প্যাকেজের protected মেম্বারকেও ডট(.) অপারেটর দিয়ে এক্সেস করা যায়

প্যাকেজ আলাদা হয়ে গেলে সংশ্লিষ্ট ক্লাসের ডিফল্ট(default) বা প্রোটেক্টেড(protected) মেম্বার গুলো নিজের মধ্যে কোনো ধরনের প্রেমের সম্পর্কে জড়াবে না। কেউ যদি চেষ্টা করেও, ভিলেন হিসেবে "কম্পাইলার এরর" তো আছে। তাহলে দেখি -

Default এক্সেসঃ দুইটি ক্লাস ভিন্ন প্যাকেজেprotected এক্সেসঃ দুইটি ক্লাস ভিন্ন প্যাকেজে
package com.main.sky; 
public class Poo{ 
   int numOfLove; 
}

package com.main.ground; 
class MasterShifu extends Poo { 
   public void Check() { 
      Poo refVar = new Poo(); 
      refVar.numOfLove = 100; 
   } 
}
package com.main.water; 
public class Poo{ 
   protected int numOfLove; 
}

package com.main.oil; 
class MasterShifu extends Poo { 
   public void Check() { 
      Poo refVar = new Poo(); 
      refVar.numOfLove = 100; 
   } 
}
ভিন্ন প্যাকেজের default মেম্বারকে ডট(.) অপারেটর দিয়ে এক্সেস করা যায় না, তাই refVar.numOfLove = 100 এর জন্য এরর দেখাবেভিন্ন প্যাকেজের protected মেম্বারকেও ডট(.) অপারেটর দিয়ে এক্সেস করা যায় না, তাই refVar.numOfLove = 100 এর জন্য এরর

কুমিরের খাঁজকাটা খাঁজকাটা গল্পের মত আবারো একই প্রশ্ন। যদি Poo পাবলিক(public) না হয়ে ডিফল্ট(default) এক্সেস যুক্ত হত, তাহলে কি কোনো এরর দেখাত? উত্তর নিহিত এই লাইনে "ডিফল্ট(default) এক্সেস যুক্ত ক্লাস শুধুমাত্র একই প্যাকেজের অন্য ক্লাসের কােছ ভিজিবল, অন্য প্যাকেজের কোনো ক্লাস এদের খুজে পাবে না।" 

একটি জিনিস কি খেয়াল করেছেন, আমরা যখন ভিন্ন প্যাকেজ প্রোটেক্টেড(protected) মেম্বারকে এক্সেস করেছি। শুধুমাত্র সাব-ক্লাস(Sub class) থেকে এক্সেস করা সম্ভব হয়েছে। তাহলে আমরা সিদ্ধান্তে আসতে পারি "সাব-ক্লাস-আউটসাইড-দ্যা-প্যাকেজ" থেকে শুধুমাত্র Inheritance এর মাধ্যমে প্রোটেক্টেড(protected) মেম্বারকে এক্সেস করা যায় আর কোনো ভাবে এক্সেস করা যায় না। Inheritance এর মাধ্যমে প্রোটেক্টেড(protected) মেম্বারকে এক্সেস করা যায় আর কোনো ভাবে এক্সেস করা যায় না।

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

পি.ডি.এফ. ডাউনলোড করতে চাইলে ক্লিক করুনঃ  ডাউনলোড

জাভাঃ IS-A রিলেশন এবং HAS-A রিলেশন

ভূমিকাঃ
চাকরির ভাইভাতে গেলেন, আপনাকে বলা হল IS-A এবং HAS-A রিলেশন কি তা বলে আপনার সামনে বসা বসদের বাধিত করতে। আপনি তো শুনেই তব্দা। এইটা খায় না মাথায় দেয়। হয়ত চাকরির ভাইভাতে এই প্রশ্ন নাও পেতে পারেন, তবে আপনি যদি OCA বা OCP পরীক্ষা দিতে চান, সেখানে অবশ্যই আসবে।
আরেহ ব্যাপার না। আপনি IS-A এবং HAS-A রিলিশনের অনেক কাজ করেছেন শুধু বই এর ভাষায় জানের না, এই যা। ওকে এক মিনিটে সমাধান।
IS-A রিলেশনঃ
IS-A রিলেশনের কনসেপ্ট হচ্ছে Inheritance এর কনসেপ্ট। IS-A দিয়ে বুঝায়, This thing is a type of that thing। যেমনঃ “সব ক্ষারকই ক্ষার”।ওকে ওয়েট, স্যরি।
যেমনঃ
  1. Potato IS-A Vegetable (আহামরি উদাহরণ না, তবে কাজ চলে)
  2. Apple IS-A Food
  3. MBW IS-A Car 
কোডে দেখি - 
public class Car{
}
public class BMW extends Car{
}
IS-A রিলেশন প্রকাশ করার জন্য দুটো কিওয়ার্ড ব্যাবহার করা হয়। Class Inheritance এর ক্ষেত্রে extends এবং Interface Implementation এর ক্ষেত্রে implements

HAS-A রিলেশনঃ
HAS-A রিলেশনশিপ কোনো ক্লাসের রেফারেন্সকে অন্য ক্লাসে ব্যাবহারের উপর ভিত্তি করে করা হয়। অন্য কথা বলা যায়, ক্লাস X HAS-A Y । যদি ক্লাস X তে Y ক্লাসের কোনো রেফারেন্স ভেরিয়েবল থাকে।


যেমনঃ
  1.   A Horse HAS-A Owner
  2.   Human HAS-A Kidney 
তাহলে- 
public class Human{
   private Kidney kidneyRefVar;
}
public class Kidney{
}
তাহলে এই লাইনটি কোডে অনুবাদ করুন।
A Horse IS-A Animal. A Horse HAS-A Owner

সারাংশঃ
IS-A রিলেশনশিপ হয় Base ক্লাস এবং Derived ক্লাসের মধ্যে। যেমনঃ
  • Programmer IS-A Person
  • Manager IS-A Person
HAS-A রিলেশনশিপ হয় দুটি ক্লাসের মধ্যে যেখানে একটি ক্লাসের রেফারেন্স অন্য ক্লাসের মেম্বার হিসেবে থাকবে। যেমনঃ
  • Mobile HAS-A Battery
  • University HAS-A Library
এই পোস্টের পি.ডি.এফ ডাউনলোড করতে চাইলেঃ ডাউনলোড

এ্যালগরিদমঃ বিগ মড (Big Mod)

যেটার জ্ঞান আবশ্যকঃ রিকার্শন।
ছোট মরিচের ঝাল দেখা যাক আজকে-
আপনাকে যদি জিজ্ঞেস করি 1754 % 81 = কি? কি বলবেন? থামেন, ক্যালকুলেটর কই!! ওকে, ক্যালকুলেটরে চেষ্টা করে দেখুন। কি!  ক্যালকুলেটর ফেইল মারছে?? ভেরী গুড।
এই কাজটা Big Mod এর মাধ্যমে খুব সহজে করতে পারি। যেখানে আমরা ছোট্ট একটি Mathematical নোটেশন ব্যাবহার করব। দেখি তাহলে –
(A * B ) % C = ( A % C * B % C ) % C
যেমনঃ-
35 % 3 = (5 * 7) % 3
            = (5 % 3 * 7 % 3 ) % 3
            = (2 * 1) % 3
            = 2
তাহলে দেখিঃ –
1755 % 81 = (17 * 1754) % 81
                            = (17 % 81 * 1754 % 81) % 81
এখন 1754 % 81 = কি?
1754 % 81 = (1727 * 1727) % 81
                           = (1727 % 81 * 1727 % 81) % 81
আবার 1727 % 81 = কি?
1727 % 81 = (17 * 1726) % 81
                           = (17 % 81 * 1726 % 81) % 81


একইভাবে আমরা পাইঃ-
1726 % 81 = (1713 % 81 * 1713 % 81) % 81
1713 % 81 = (17% 81 * 1712 % 81) % 81
1712 % 81 = (176 % 81 * 176 % 81) % 81
176 % 81 = (173 % 81 * 173 % 81) % 81
173 % 81 = (17 % 81 * 172 % 81) % 81
172 % 81 = (17 % 81 * 17 % 81) % 81
17 % 81 = 17

এখন নিচ থেকে ভ্যালূগুলো উপরের Equation গুলোতে বসিয়ে একটু ক্যালকুলেট করলে উত্তর পাওয়া যাবে।

নিচের ছবিটি দেখি এখন –



 * যদি উপরের Equation গুলোর একটিও বুঝতে না পারেন তাহলে আবার দেখুন নিচে যাওয়ার দরকার নেই।

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

মনেকরি,
base হচ্ছে  = b
power হচ্ছে = p
Divisor হচ্ছে = d;

যখন পাওয়ার বিজোড়, আমরা করেছি,
(b % d * b (p-1) % d ) % d

যখন পাওয়ার জোড়, আমরা করেছি,
(b (p/2) % d * b (p/2) % d ) % d
বা, square( b (p/2) % d ) % d

এই কাজটা আমরা পাওয়ার জিরো হওয়ার আগ পর্যন্ত করেছি। মানে p থেকে 1 পর্যন্ত। তাহলে আমাদের কাজ শেষ হয়ে গিয়েছে কখন? যখন p এর মান জিরো হয়ে গিয়েছে। মানে রিকার্শন ব্রেক হওয়ার কন্ডিশন হচ্ছে এটি, যখন p = 0

আর একটা ব্যাপার দেখুন আমরা লাস্ট স্টেপ থেকে মান তার আগের স্টেপে পাঠিয়ে দিয়েছি।

এখন তাহলে কোড করি –
মনেকরি আমাদের ফাংশনের নামে bigMod যার ৩ টি parameter (b,p,d) আছে –

int bigMod(int b, int p, int d)
{
   if(p == 0 )
      return 1;   
   if( p % 2 != 0 )
   {
      return ( b % d * bigMod( b, p-1, d ) ) % d ;
   }
   else
   {
      return ( square( bigMod( b, p/2, d ) ) ) % d;   
   }
}
int square(int n)
{
   return n*n;
}
তাহলে আমরা এ্যালগরিদম ও কোড দুটোই বুঝতে পেরেছি। ঝটপট তাহলে ১ টি ACM সলভ করে ফেলি।
ACM প্রবলেমঃ 374 - Big Mod
পিডিএফ হিসেবে ডাউনলোড করুনঃ ডাউনলোড