CodeGym /Java Blog /এলোমেলো /নেস্টেড ক্লাসের উত্তরাধিকারের উদাহরণ
John Squirrels
লেভেল 41
San Francisco

নেস্টেড ক্লাসের উত্তরাধিকারের উদাহরণ

এলোমেলো দলে প্রকাশিত
ওহে! আজ আমরা একটি গুরুত্বপূর্ণ প্রক্রিয়া দেখব: নেস্টেড ক্লাসে উত্তরাধিকার। আপনি কি কখনও ভেবে দেখেছেন যে আপনি যদি একটি নেস্টেড ক্লাসকে অন্য কোনও ক্লাসের উত্তরাধিকারী করতে চান তবে আপনি কী করবেন। যদি না হয়, আমাকে বিশ্বাস করুন: এই পরিস্থিতি বিভ্রান্তিকর হতে পারে, কারণ অনেক সূক্ষ্মতা আছে।
  1. আমরা কি একটি নেস্টেড ক্লাস তৈরি করছি কিছু ক্লাসের উত্তরাধিকারী? নাকি আমরা কিছু শ্রেণীকে একটি নেস্টেড ক্লাস উত্তরাধিকারী করে তুলছি?
  2. শিশু/অভিভাবক শ্রেণী কি একটি সাধারণ পাবলিক শ্রেণী, নাকি এটি একটি নেস্টেড ক্লাস?
  3. অবশেষে, এই সমস্ত পরিস্থিতিতে আমরা কোন ধরণের নেস্টেড ক্লাস ব্যবহার করি?
এই সমস্ত প্রশ্নের অনেক সম্ভাব্য উত্তর আছে, আপনার মাথা ঘুরবে :) আপনি জানেন, আমরা একটি জটিল সমস্যাকে সহজ অংশে ভাগ করে সমাধান করতে পারি। এটা করা যাক. আসুন আমরা দুটি দৃষ্টিকোণ থেকে নেস্টেড ক্লাসের প্রতিটি গ্রুপকে বিবেচনা করি: কে প্রতিটি ধরণের নেস্টেড ক্লাসের উত্তরাধিকারী হতে পারে এবং কারা এটি উত্তরাধিকারী হতে পারে। স্ট্যাটিক নেস্টেড ক্লাস দিয়ে শুরু করা যাক।

স্ট্যাটিক নেস্টেড ক্লাস

নেস্টেড ক্লাসের উত্তরাধিকারের উদাহরণ - 2তাদের উত্তরাধিকার নিয়ম সবচেয়ে সহজ। এখানে আপনি আপনার মনের ইচ্ছা প্রায় সবকিছু করতে পারেন। একটি স্ট্যাটিক নেস্টেড ক্লাস উত্তরাধিকারী হতে পারে:
  • একটি সাধারণ ক্লাস
  • একটি স্ট্যাটিক নেস্টেড শ্রেণী যা একটি বহিরাগত শ্রেণী বা তার পূর্বপুরুষদের মধ্যে ঘোষণা করা হয়
স্ট্যাটিক নেস্টেড ক্লাসের উপর আমাদের পাঠ থেকে একটি উদাহরণ স্মরণ করুন।

public class Boeing737 {

   private int manufactureYear;
   private static int maxPassengersCount = 300;

   public Boeing737(int manufactureYear) {
       this.manufactureYear = manufactureYear;
   }

   public int getManufactureYear() {
       return manufactureYear;
   }

   public static class Drawing {
      
       public static int getMaxPassengersCount() {
          
           return maxPassengersCount;
       }
   }
}
আসুন কোডটি পরিবর্তন করার চেষ্টা করি এবং একটি Drawingস্ট্যাটিক নেস্টেড ক্লাস এবং এর বংশধর তৈরি করি — Boeing737Drawing

public class Boeing737 {

   private int manufactureYear;
   private static int maxPassengersCount = 300;

   public Boeing737(int manufactureYear) {
       this.manufactureYear = manufactureYear;
   }

   public int getManufactureYear() {
       return manufactureYear;
   }

   public static class Drawing {
      
   }
  
   public static class Boeing737Drawing extends Drawing {

       public static int getMaxPassengersCount() {

           return maxPassengersCount;
       }
   }
}
আপনি দেখতে পারেন, কোন সমস্যা নেই. এমনকি আমরা ক্লাসটি বের করতে পারি Drawingএবং স্ট্যাটিক নেস্টেড ক্লাসের পরিবর্তে এটিকে একটি সাধারণ পাবলিক শ্রেণীতে পরিণত করতে পারি — কিছুই পরিবর্তন হবে না।

public class Drawing {
  
}

public class Boeing737 {

   private int manufactureYear;
   private static int maxPassengersCount = 300;

   public Boeing737(int manufactureYear) {
       this.manufactureYear = manufactureYear;
   }

   public int getManufactureYear() {
       return manufactureYear;
   }

   public static class Boeing737Drawing extends Drawing {

       public static int getMaxPassengersCount() {

           return maxPassengersCount;
       }
   }
}
আমরা এই বুঝি। কিন্তু কোন ক্লাস একটি স্ট্যাটিক নেস্টেড ক্লাস উত্তরাধিকারী হতে পারে? কার্যত কোন! নেস্টেড/নন-নেস্টেড, স্ট্যাটিক/নন-স্ট্যাটিক — এটা কোন ব্যাপার না। এখানে আমরা Boeing737Drawingভিতরের ক্লাসটিকে স্ট্যাটিক নেস্টেড ক্লাসের উত্তরাধিকারী করি Drawing:

public class Boeing737 {

   private int manufactureYear;
   private static int maxPassengersCount = 300;

   public Boeing737(int manufactureYear) {
       this.manufactureYear = manufactureYear;
   }

   public int getManufactureYear() {
       return manufactureYear;
   }

   public static class Drawing {
      
   }

   public class Boeing737Drawing extends Drawing {

       public int getMaxPassengersCount() {

           return maxPassengersCount;
       }
   }
}
আপনি এই মত একটি উদাহরণ তৈরি করতে পারেন Boeing737Drawing:

public class Main {

   public static void main(String[] args) {

      Boeing737 boeing737 = new Boeing737(1990);
      Boeing737.Boeing737Drawing drawing = boeing737.new Boeing737Drawing();
      System.out.println(drawing.getMaxPassengersCount());

   }

}
যদিও আমাদের Boeing737Drawingক্লাস একটি স্ট্যাটিক ক্লাস উত্তরাধিকারসূত্রে পেয়েছে, তবে এটি নিজেই স্ট্যাটিক নয়! ফলস্বরূপ, এটি সর্বদা বাইরের শ্রেণীর একটি উদাহরণ প্রয়োজন হবে। আমরা ক্লাস Boeing737Drawingথেকে ক্লাসটি সরিয়ে Boeing737এটিকে একটি সাধারণ পাবলিক ক্লাস করতে পারি। কিছুই পরিবর্তন. এটি এখনও Drawingস্ট্যাটিক নেস্টেড ক্লাসের উত্তরাধিকারী হতে পারে।

public class Boeing737 {

   private int manufactureYear;
   public static int maxPassengersCount = 300;

   public Boeing737(int manufactureYear) {
       this.manufactureYear = manufactureYear;
   }

   public int getManufactureYear() {
       return manufactureYear;
   }

   public static class Drawing {

   }
}

public class Boeing737Drawing extends Boeing737.Drawing {

   public int getMaxPassengersCount() {

       return Boeing737.maxPassengersCount;
   
}
একমাত্র গুরুত্বপূর্ণ বিষয় হল এই ক্ষেত্রে আমাদের স্ট্যাটিক maxPassengersCountপরিবর্তনশীলকে সর্বজনীন করতে হবে। যদি এটি ব্যক্তিগত থেকে যায়, তাহলে একটি সাধারণ পাবলিক শ্রেণীর এটিতে অ্যাক্সেস থাকবে না। আমরা স্ট্যাটিক ক্লাস খুঁজে বের করেছি! :) এখন আমরা ভিতরের ক্লাসে চলে যাই। এগুলি 3 প্রকারে আসে: সাধারণ অভ্যন্তরীণ শ্রেণী, স্থানীয় শ্রেণী এবং বেনামী অভ্যন্তরীণ শ্রেণী। নেস্টেড ক্লাসের উত্তরাধিকারের উদাহরণ - 3আবার, সরল থেকে জটিলে যাওয়া যাক :)

বেনামী ভিতরের ক্লাস

একটি বেনামী অভ্যন্তরীণ শ্রেণী অন্য শ্রেণীর উত্তরাধিকারী হতে পারে না। অন্য কোন শ্রেণী একটি বেনামী শ্রেণীর উত্তরাধিকারী হতে পারে না। এটা কোন সহজ হতে পারে না! :)

স্থানীয় ক্লাস

স্থানীয় ক্লাস (যদি আপনি ভুলে গেছেন) অন্য ক্লাসের কোড ব্লকের মধ্যে ঘোষণা করা হয়। প্রায়শই, এটি বাইরের শ্রেণীর কিছু পদ্ধতির ভিতরে ঘটে। যৌক্তিকভাবে, একই পদ্ধতির (বা কোড ব্লক) মধ্যে শুধুমাত্র অন্যান্য স্থানীয় ক্লাস একটি স্থানীয় ক্লাস উত্তরাধিকারী হতে পারে। এখানে একটি উদাহরণ:

public class PhoneNumberValidator {

   public void validatePhoneNumber(final String number) {

       class PhoneNumber {

           private String phoneNumber;

           public PhoneNumber() {
               this.phoneNumber = number;
           }

           public String getPhoneNumber() {
               return phoneNumber;
           }

           public void setPhoneNumber(String phoneNumber) {
               this.phoneNumber = phoneNumber;
           }
       }

       class CellPhoneNumber extends PhoneNumber {

       }

       class LandlinePhoneNumber extends PhoneNumber {
          
          
       }

       // ...number validation code
   }
}
এটি স্থানীয় ক্লাসে আমাদের পাঠের কোড। আমাদের নম্বর ভ্যালিডেটর ক্লাসের একটি PhoneNumberস্থানীয় ক্লাস আছে। আমাদের যদি দুটি স্বতন্ত্র সত্ত্বার প্রতিনিধিত্ব করার প্রয়োজন হয়, উদাহরণস্বরূপ, একটি মোবাইল ফোন নম্বর এবং একটি ল্যান্ডলাইন ফোন নম্বর, আমরা শুধুমাত্র একই পদ্ধতিতে এটি করতে পারি। কারণটি সহজ: একটি স্থানীয় ক্লাসের সুযোগ পদ্ধতি (কোড ব্লক) যেখানে এটি ঘোষণা করা হয় সেখানে সীমাবদ্ধ। ফলস্বরূপ, আমরা এটি বাহ্যিকভাবে ব্যবহার করতে সক্ষম হব না (শ্রেণীর উত্তরাধিকার সহ)। তবে, স্থানীয় শ্রেণীর মধ্যেই উত্তরাধিকারের সম্ভাবনা অনেক বিস্তৃত! একটি স্থানীয় শ্রেণী উত্তরাধিকারী হতে পারে:
  1. একটা সাধারন ক্লাস।
  2. একটি অভ্যন্তরীণ শ্রেণী যা স্থানীয় শ্রেণীর বা তার পূর্বপুরুষদের মধ্যে একই শ্রেণীতে ঘোষণা করা হয়।
  3. একই পদ্ধতিতে ঘোষিত আরেকটি স্থানীয় ক্লাস (কোড ব্লক)।
প্রথম এবং তৃতীয় পয়েন্টগুলি সুস্পষ্ট দেখায়, কিন্তু দ্বিতীয়টি কিছুটা বিভ্রান্তিকর :/ আসুন দুটি উদাহরণ দেখি। উদাহরণ 1 — "একটি স্থানীয় শ্রেণিকে স্থানীয় শ্রেণির মতো একই শ্রেণিতে ঘোষণা করা একটি অভ্যন্তরীণ শ্রেণিকে উত্তরাধিকারী করা":

public class PhoneNumberValidator {

   class PhoneNumber {

       private String phoneNumber;

       public PhoneNumber(String phoneNumber) {
           this.phoneNumber = phoneNumber;
       }

       public String getPhoneNumber() {
           return phoneNumber;
       }

       public void setPhoneNumber(String phoneNumber) {
           this.phoneNumber = phoneNumber;
       }
   }

   public void validatePhoneNumber(final String number) {

       class CellPhoneNumber extends PhoneNumber {

           public CellPhoneNumber(String phoneNumber) {
               super(number);
           }
       }

       class LandlinePhoneNumber extends PhoneNumber {

           public LandlinePhoneNumber(String phoneNumber) {
               super(number);
           }
       }

       // ...number validation code
   }
}
এখানে আমরা মেথড PhoneNumberথেকে ক্লাসটি সরিয়ে validatePhoneNumber()স্থানীয় ক্লাসের পরিবর্তে এটিকে একটি অভ্যন্তরীণ ক্লাস বানিয়েছি। এটি আমাদের 2টি স্থানীয় ক্লাসকে উত্তরাধিকারী করতে আমাদের বাধা দেয় না। উদাহরণ 2 — "... বা এই শ্রেণীর পূর্বপুরুষদের মধ্যে।" এখন এই ইতিমধ্যে আরো আকর্ষণীয়. আমরা PhoneNumberউত্তরাধিকার শৃঙ্খলে আরও উঁচুতে যেতে পারি। আসুন একটি বিমূর্ত AbstractPhoneNumberValidatorশ্রেণী ঘোষণা করি, যা আমাদের শ্রেণীর পূর্বপুরুষ হয়ে উঠবে PhoneNumberValidator:

public abstract class AbstractPhoneNumberValidator {

   class PhoneNumber {

       private String phoneNumber;

       public PhoneNumber(String phoneNumber) {
           this.phoneNumber = phoneNumber;
       }

       public String getPhoneNumber() {
           return phoneNumber;
       }

       public void setPhoneNumber(String phoneNumber) {
           this.phoneNumber = phoneNumber;
       }
   }

}
আপনি দেখতে পাচ্ছেন, আমরা কেবল এটি ঘোষণা করিনি - আমরা PhoneNumberএটিতে অভ্যন্তরীণ শ্রেণীকেও স্থানান্তরিত করেছি। যাইহোক, এর বংশধরে PhoneNumberValidator, পদ্ধতিতে ঘোষিত স্থানীয় ক্লাসগুলি PhoneNumberকোনও সমস্যা ছাড়াই উত্তরাধিকারী হতে পারে!

public class PhoneNumberValidator extends AbstractPhoneNumberValidator {

   public void validatePhoneNumber(final String number) {

       class CellPhoneNumber extends PhoneNumber {

           public CellPhoneNumber(String phoneNumber) {
               super(number);
           }
       }

       class LandlinePhoneNumber extends PhoneNumber {

           public LandlinePhoneNumber(String phoneNumber) {
               super(number);
           }
       }

       // ...number validation code
   }
}
উত্তরাধিকার সম্পর্কের কারণে, একটি বংশধর শ্রেণীর ভিতরের স্থানীয় শ্রেণীগুলি পূর্বপুরুষের ভিতরের শ্রেণীগুলিকে "দেখে"। এবং অবশেষে, চলুন শেষ গ্রুপে এগিয়ে যাই :)

অভ্যন্তরীণ ক্লাস

একই বহিরাগত শ্রেণীতে ঘোষিত একটি অভ্যন্তরীণ শ্রেণী (বা এর বংশধরে) অন্য একটি অভ্যন্তরীণ শ্রেণীর উত্তরাধিকারী হতে পারে। আসুন ভিতরের ক্লাসের পাঠ থেকে সাইকেল সহ আমাদের উদাহরণ ব্যবহার করে এটি অন্বেষণ করি।

public class Bicycle {

   private String model;
   private int maxWeight;

   public Bicycle(String model, int maxWeight) {
       this.model = model;
       this.maxWeight = maxWeight;
   }

   public void start() {
       System.out.println("Let's go!");
   }

   class Seat {

       public void up() {

           System.out.println("Seat up!");
       }

       public void down() {

           System.out.println("Seat down!");
       }
   }

   class SportSeat extends Seat {
      
       // ...methods
   }
}
এখানে আমরা ক্লাসের Seatভিতরে ভিতরের শ্রেণী ঘোষণা করেছি Bicycle। একটি বিশেষ ধরনের রেসিং সিট, SportSeatএটি উত্তরাধিকার সূত্রে প্রাপ্ত। তবে, আমরা একটি পৃথক "রেসিং সাইকেল" টাইপ তৈরি করতে পারি এবং এটিকে একটি পৃথক ক্লাসে রাখতে পারি:

public class SportBicycle extends Bicycle {
  
   public SportBicycle(String model, int maxWeight) {
       super(model, maxWeight);
   }

  
   class SportSeat extends Seat {

       public void up() {

           System.out.println("Seat up!");
       }

       public void down() {

           System.out.println("Seat down!");
       }
   }
}
এটিও একটি বিকল্প। বংশধরের অভ্যন্তরীণ শ্রেণী ( SportBicycle.SportSeat) পূর্বপুরুষের অভ্যন্তরীণ শ্রেণীগুলিকে "দেখে" এবং তাদের উত্তরাধিকারী হতে পারে। অভ্যন্তরীণ ক্লাস উত্তরাধিকারসূত্রে একটি অত্যন্ত গুরুত্বপূর্ণ বৈশিষ্ট্য রয়েছে! আগের দুটি উদাহরণে, আমাদের SportSeatক্লাসটি একটি অভ্যন্তরীণ শ্রেণী ছিল। কিন্তু আমরা যদি SportSeatএকটি সাধারণ পাবলিক শ্রেণী তৈরি করার সিদ্ধান্ত নিই যা একই সাথে Seatঅভ্যন্তরীণ শ্রেণীর উত্তরাধিকারী হয়?

// Error! No enclosing instance of type 'Bicycle' is in scope
class SportSeat extends Bicycle.Seat {

   public SportSeat() {

   }

   public void up() {

       System.out.println("Seat up!");
   }

   public void down() {

       System.out.println("Seat down!");
   }
}
আমরা একটি ত্রুটি পেয়েছি! আপনি অনুমান করতে পারেন কেন? :) এটা সব সোজা. আমরা যখন Bicycle.Seatঅভ্যন্তরীণ শ্রেণী সম্পর্কে কথা বলেছিলাম, তখন আমরা উল্লেখ করেছি যে বাইরের শ্রেণীর একটি উদাহরণের একটি রেফারেন্স অন্তর্নিহিত শ্রেণীর নির্মাণকারীর কাছে অন্তর্নিহিতভাবে প্রেরণ করা হয়েছে। Seatএর মানে হল যে আপনি একটি বস্তু তৈরি না করে একটি Bicycleবস্তু তৈরি করতে পারবেন না । কিন্তু একটি সৃষ্টি সম্পর্কে কি SportSeat? এর বিপরীতে Seat, বহিরাগত শ্রেণীর একটি উদাহরণে কনস্ট্রাক্টরকে অন্তর্নিহিতভাবে প্রেরণ করার জন্য এটিতে এই অন্তর্নির্মিত প্রক্রিয়া নেই। S পর্যন্ত, একটি Bicycleবস্তু ছাড়া, আমরা একটি SportSeatবস্তু তৈরি করতে পারি না, যেমনটি ক্ষেত্রে Seat। অতএব, আমাদের জন্য শুধুমাত্র একটি জিনিস বাকি আছে - স্পষ্টভাবে কনস্ট্রাক্টরকে একটি বস্তুর SportSeatএকটি রেফারেন্স পাঠান। Bicycleএটি কীভাবে করবেন তা এখানে:

class SportSeat extends Bicycle.Seat {

   public SportSeat(Bicycle bicycle) {

       bicycle.super();
   }

   public void up() {

       System.out.println("Seat up!");
   }

   public void down() {

       System.out.println("Seat down!");
   }
}
আমরা এখন ব্যবহার করে সুপারক্লাস কনস্ট্রাক্টরকে কল করি super(); , যদি আমরা একটি অবজেক্ট তৈরি করতে চাই তবে SportSeatকিছুই আমাদের এটি করতে বাধা দেবে না:

public class Main {

   public static void main(String[] args) {

       Bicycle bicycle = new Bicycle("Peugeot", 120);
       SportSeat peugeotSportSeat = new SportSeat(bicycle);

   }
}
উফফ! এই পাঠটি বরং দীর্ঘ ছিল :) কিন্তু আপনি অনেক কিছু শিখেছেন! এখন কিছু কাজ সমাধান করার সময়! :)
মন্তব্য
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION