CodeGym /Java Blog /Random /Mga halimbawa ng inheritance ng mga nested class
John Squirrels
Antas
San Francisco

Mga halimbawa ng inheritance ng mga nested class

Nai-publish sa grupo
Hi! Ngayon ay titingnan natin ang isang mahalagang mekanismo: pamana sa mga nested na klase. Naisip mo na ba kung ano ang iyong gagawin kung kailangan mong gawin ang isang nested class na magmana ng ibang klase. Kung hindi, maniwala ka sa akin: ang sitwasyong ito ay maaaring nakalilito, dahil mayroong maraming mga nuances.
  1. Gumagawa ba tayo ng nested class na magmana ng ilang klase? O ginagawa ba natin ang ilang klase na magmana ng nested class?
  2. Ang klase ba ng bata/magulang ay isang ordinaryong pampublikong klase, o isa rin itong nested na klase?
  3. Panghuli, anong uri ng mga nested na klase ang ginagamit namin sa lahat ng sitwasyong ito?
Napakaraming posibleng sagot sa lahat ng tanong na ito, iikot ang iyong ulo :) Tulad ng alam mo, malulutas natin ang isang kumplikadong problema sa pamamagitan ng paghahati nito sa mas simpleng mga bahagi. Gawin natin yan. Isaalang-alang natin ang bawat pangkat ng mga nested na klase sa turn mula sa dalawang pananaw: sino ang maaaring magmana ng bawat uri ng nested class, at kung sino ang maaari nitong magmana. Magsimula tayo sa mga static na nested na klase.

Mga static na nested na klase

Mga halimbawa ng pamana ng mga nested class - 2Ang kanilang mga panuntunan sa pamana ay ang pinakasimple. Dito maaari mong gawin ang halos anumang naisin ng iyong puso. Ang isang static na nested na klase ay maaaring magmana ng:
  • isang ordinaryong klase
  • isang static na nested class na idineklara sa isang outer class o sa mga ninuno nito
Alalahanin ang isang halimbawa mula sa aming aralin sa mga static na nested na klase.

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;
       }
   }
}
Subukan nating baguhin ang code at lumikha ng isang Drawingstatic na nested class at ang descendant nito — 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;
       }
   }
}
Tulad ng nakikita mo, walang problema. Maaari pa nga nating i-pull out ang Drawingklase at gawin itong ordinaryong pampublikong klase sa halip na isang static na nested na klase — walang magbabago.

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;
       }
   }
}
Naiintindihan namin ito. Ngunit anong mga klase ang maaaring magmana ng isang static na nested na klase? Halos kahit ano! Nested/non-nested, static/non-static — hindi mahalaga. Dito ginagawa namin ang Boeing737Drawingpanloob na klase na magmana ng Drawingstatic na nested na klase:

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;
       }
   }
}
Maaari kang lumikha ng isang halimbawa ng Boeing737Drawingganito:

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());

   }

}
Bagama't ang aming Boeing737Drawingklase ay nagmamana ng isang static na klase, ito ay hindi static mismo! Bilang resulta, ito ay palaging nangangailangan ng isang halimbawa ng panlabas na klase. Maaari nating alisin ang Boeing737Drawingklase sa Boeing737klase at gawin itong isang simpleng pampublikong klase. Walang nagbago. Maaari pa rin itong magmana ng Drawingstatic na nested na klase.

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;
   
}
Ang tanging mahalagang punto ay sa kasong ito kailangan nating gawing maxPassengersCountpampubliko ang static na variable. Kung ito ay mananatiling pribado, kung gayon ang isang ordinaryong pampublikong klase ay hindi magkakaroon ng access dito. Nalaman namin ang mga static na klase! :) Ngayon ay lumipat tayo sa mga panloob na klase. May 3 uri ang mga ito: mga simpleng panloob na klase, lokal na klase, at hindi kilalang panloob na klase. Mga halimbawa ng pamana ng mga nested class - 3Muli, lumipat tayo mula sa simple patungo sa kumplikado :)

Anonymous na mga panloob na klase

Ang isang hindi kilalang panloob na klase ay hindi maaaring magmana ng isa pang klase. Walang ibang klase ang maaaring magmana ng anonymous na klase. Hindi ito maaaring maging mas simple! :)

Mga lokal na klase

Ang mga lokal na klase (kung sakaling nakalimutan mo) ay idineklara sa loob ng isang bloke ng code ng isa pang klase. Kadalasan, nangyayari ito sa loob ng ilang paraan ng panlabas na klase. Sa lohikal na paraan, tanging ang iba pang mga lokal na klase sa loob ng parehong pamamaraan (o block ng code) ang maaaring magmana ng isang lokal na klase. Narito ang isang halimbawa:

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
   }
}
Ito ang code mula sa aming aralin sa mga lokal na klase. Ang aming klase ng validator ng numero ay may PhoneNumberlokal na klase. Kung kailangan namin itong kumatawan sa dalawang natatanging entity, halimbawa, isang numero ng mobile phone at isang landline na numero ng telepono, magagawa lang namin ito sa loob ng parehong paraan. Ang dahilan ay simple: ang saklaw ng lokal na klase ay limitado sa pamamaraan (code block) kung saan ito idineklara. Bilang resulta, hindi namin ito magagamit sa labas (kabilang ang para sa class inheritance). Gayunpaman, ang mga posibilidad para sa pamana sa loob ng lokal na klase mismo ay mas malawak! Ang isang lokal na klase ay maaaring magmana ng:
  1. Isang ordinaryong klase.
  2. Isang panloob na uri na idineklara sa parehong klase ng lokal na klase o sa isa sa mga ninuno nito.
  3. Ang isa pang lokal na klase ay ipinahayag sa parehong pamamaraan (block ng code).
Ang una at pangatlong puntos ay mukhang halata, ngunit ang pangalawa ay medyo nakakalito :/ Tingnan natin ang dalawang halimbawa. Halimbawa 1 — "Ang paggawa ng lokal na klase ay magmana ng panloob na klase na idineklara sa parehong klase ng lokal na klase":

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
   }
}
Dito namin inalis ang PhoneNumberklase mula sa validatePhoneNumber()pamamaraan at ginawa itong isang panloob na klase sa halip na isang lokal na klase. Hindi ito pumipigil sa amin na gawin itong mamanahin ng aming 2 lokal na klase. Halimbawa 2 — "... o sa mga ninuno ng klase na ito." Ngayon ito ay mas kawili-wili. Maaari tayong lumipat PhoneNumbernang mas mataas sa chain ng mana. Magdeklara tayo ng abstract AbstractPhoneNumberValidatorna klase, na magiging ninuno ng ating PhoneNumberValidatorklase:

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;
       }
   }

}
Gaya ng nakikita mo, hindi lang namin ito idineklara — inilipat din namin ang PhoneNumberpanloob na klase dito. Gayunpaman, sa inapo nito PhoneNumberValidator, ang mga lokal na klase na idineklara sa mga pamamaraan ay maaaring magmana PhoneNumbernang walang anumang problema!

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
   }
}
Dahil sa relasyon sa mana, ang mga lokal na klase sa loob ng isang descendant na klase ay "nakikita" ang mga panloob na klase sa loob ng isang ninuno. At sa wakas, magpatuloy tayo sa huling grupo :)

Mga panloob na klase

Ang isang panloob na uri na idineklara sa parehong panlabas na uri (o sa inapo nito) ay maaaring magmana ng isa pang panloob na uri. Tuklasin natin ito gamit ang ating halimbawa sa mga bisikleta mula sa aralin sa mga panloob na klase.

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
   }
}
Dito namin idineklara ang Seatinner class sa loob ng Bicycleklase. Isang espesyal na uri ng racing seat, SportSeat, ang namamana nito. Ngunit, maaari tayong lumikha ng isang hiwalay na uri ng "karera ng bisikleta" at ilagay ito sa isang hiwalay na klase:

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!");
       }
   }
}
Isa rin itong opsyon. "Nakikita" ng panloob na klase ng inapo ( SportBicycle.SportSeat) ang mga panloob na klase ng ninuno at maaaring magmana ng mga ito. Ang pagmamana ng mga panloob na klase ay may isang napakahalagang tampok! Sa nakaraang dalawang halimbawa, ang aming SportSeatklase ay isang panloob na klase. Ngunit paano kung magpasya tayong gumawa SportSeatng ordinaryong pampublikong klase na sabay-sabay na nagmamana ng Seatpanloob na uri?

// 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!");
   }
}
Nagkaroon kami ng error! Maaari mo bang hulaan kung bakit? :) Diretso lang lahat. Nang pag-usapan natin ang tungkol sa Bicycle.Seatpanloob na klase, binanggit namin na ang isang sanggunian sa isang halimbawa ng panlabas na klase ay tahasang ipinapasa sa tagabuo ng panloob na klase. Nangangahulugan ito na hindi ka makakalikha ng isang Seatbagay nang hindi gumagawa ng isang Bicyclebagay. Ngunit ano ang tungkol sa paglikha ng isang SportSeat? Hindi tulad ng Seat, wala itong built-in na mekanismo para sa tahasang pagpasa sa tagabuo ng isang sanggunian sa isang halimbawa ng panlabas na klase. Hanggang sa, kung walang Bicyclebagay, hindi tayo makakalikha ng isang SportSeatbagay, tulad ng sa kaso ng Seat. Samakatuwid, isang bagay na lang ang natitira para sa amin - tahasang ipasa sa SportSeatconstructor ang isang reference sa isang Bicyclebagay. Narito kung paano ito gawin:

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!");
   }
}
Tinatawag namin ang superclass constructor gamit super(); ang Now, kung gusto naming lumikha ng isang SportSeatbagay, walang makakapigil sa aming gawin ito:

public class Main {

   public static void main(String[] args) {

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

   }
}
Phew! Medyo mahaba ang lesson na ito :) Pero marami kang natutunan! Ngayon ay oras na upang malutas ang ilang mga gawain! :)
Mga komento
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION