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