JavaRush /Java Blogu /Random-AZ /Yuvalanmış siniflərin miras qalması

Yuvalanmış siniflərin miras qalması

Qrupda dərc edilmişdir
Salam! Bu gün biz mühüm mexanizmin işinə baxacağıq - yuvalanmış siniflərdə miras. Bilmirəm ki, başqa sinifdən iç-içə sinfi miras almalı olduğunuz zaman nə edəcəyinizi düşünmüsünüzmü. Yoxdursa, inanın: bu vəziyyət çaşdırıcı ola bilər, çünki burada bir çox nüans var:
  1. Biz hansısa sinifdən iç içə bir sinfi miras alırıq, yoxsa iç içə bir sinifdən başqa bir sinfi miras alırıq?
  2. Varisi/miras adi ictimai sinifdir, yoxsa o, həm də iç-içə sinifdir?
  3. Nəhayət, bütün bu vəziyyətlərdə tam olaraq hansı növ iç-içə siniflərdən istifadə edirik?
Bütün bu suallara cavab versəniz, o qədər mümkün cavablar olacaq ki, başınız fırlanacaq :) Bildiyiniz kimi, mürəkkəb məsələni həll etmək üçün onu daha sadə hissələrə bölmək lazımdır. Biz bunu edəcəyik. Gəlin hər bir yuvalanmış siniflər qrupuna növbə ilə iki nöqteyi-nəzərdən baxaq: bu tip iç içə sinifdən kim vərəsəlik ala bilər və kimdən miras ala bilər. Statik daxili siniflərdən başlayaq.

Statik iç-içə siniflər

Daxili siniflərin irsiyyət nümunələri - 2Onların varislik qaydaları ən sadədir. Burada ürəyinizin istədiyi hər şeyi edə bilərsiniz. Statik yuvalanmış sinif aşağıdakılardan miras alına bilər:
  • adi sinif
  • xarici sinifdə və ya onun əcdadlarında elan edilən statik yuvalanmış sinif
Statik yuvalanmış siniflər haqqında mühazirədən nümunəni xatırlayaq.
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;
       }
   }
}
DrawingKodu dəyişdirməyə və statik iç içə sinif və onun nəslini yaratmağa çalışaq - 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;
       }
   }
}
Gördüyünüz kimi problem yoxdur. Biz sinfi bütövlükdə silə Drawingvə onu statik daxili sinif əvəzinə adi ictimai sinif edə bilərik - heç nə dəyişməyəcək.
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;
       }
   }
}
Bu sıralanır. Və hansı siniflər statik bir yuvadan miras qala bilər? Demək olar ki, hər hansı! İç içə/müntəzəm, statik/statik olmayan - fərqi yoxdur. Burada biz daxili sinfi Boeing737Drawingstatik yuvalanmış sinifdən miras alırıq 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;
       }
   }
}
Boeing737DrawingBelə bir nümunə yarada bilərsiniz:
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());

   }

}
Sinifimiz Boeing737Drawingstatik sinifdən miras olsa da, özü statik deyil! Buna görə də həmişə xarici sinif nümunəsinə ehtiyac duyacaq. Biz sinfi Boeing737Drawingsinifdən çıxarıb Boeing737onu sadəcə ictimai sinif edə bilərik. Heç nə dəyişməyəcək - o, həmçinin statik yuvadan miras qala bilər 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;

}
Yeganə vacib məqam: bu halda statik dəyişəni ictimai etmək lazımdır maxPassengersCount. Şəxsi olaraq qalsa, normal ictimai sinifin ona girişi olmayacaq. Statik sinifləri sıraladıq! :) İndi keçək daxili dərslərə. Xatırladığınız kimi, onların 3 növü var: sadəcə olaraq daxili siniflər, yerli siniflər və anonim daxili siniflər. Daxili siniflərin irsiyyət nümunələri - 3Yenə sadədən mürəkkəbə keçək :)

Anonim daxili siniflər

Anonim daxili sinif başqa sinifdən miras qala bilməz. Heç bir başqa sinif anonim sinifdən varis ola bilməz. Daha sadə ola bilməzdi! :)

Yerli siniflər

Yerli siniflər (unutduğunuz halda) başqa bir sinfin kod blokunda elan edilir. Ən tez-tez - bu xarici sinifin bəzi metodu içərisində. Məntiqlidir ki, yalnız eyni metod (və ya blok) daxilində olan digər yerli siniflər yerli sinifdən miras ala bilər. Budur bir nümunə:
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 {


       }

       //...code валидации номера
   }
}
Bu, yerli siniflər haqqında mühazirəmizin kodudur. Nömrə təsdiqləyici sinifinin içərisində yerli sinifimiz var PhoneNumber- telefon nömrəsi. Əgər məqsədlərimiz üçün ondan iki ayrı obyekti, məsələn, mobil telefon nömrəsini və stasionar telefon nömrəsini çıxarmaq lazımdırsa, biz bunu yalnız eyni üsulla edə bilərik. Səbəb sadədir: lokal sinfin əhatə dairəsi elan edildiyi metodun (blokun) daxilindədir. Buna görə də biz onu hansısa şəkildə xaricdən istifadə edə bilməyəcəyik (o cümlədən miras üçün). Bununla belə, yerli sinfin özünün miras üçün daha geniş imkanları var! Yerli sinif aşağıdakılardan miras qala bilər:
  1. Adi sinif.
  2. Yerli siniflə eyni sinifdə və ya əcdadlarında elan edilən daxili sinif.
  3. Eyni metodda (blokda) elan edilmiş başqa bir yerli sinifdən.
Birinci və üçüncü məqamlar açıq görünür, amma ikincisi bir az qarışıqdır :/ İki misala baxaq. Misal 1 - “yerli siniflə eyni sinifdə elan edilmiş daxili sinifdən yerli sinfi miras almaq”:
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);
           }
       }

       //...code валидации номера
   }
}
Burada biz sinfi PhoneNumbermetoddan çıxardıq validatePhoneNumber()və yerli əvəzinə daxili etdik. Bu, bizim 2 yerli sinifimizi ondan miras almağa mane olmur. Misal 2 – “...yaxud bu sinfin əcdadlarında.” Burada daha maraqlı olur. PhoneNumberBiz onu miras zəncirində daha da yuxarı qaldıra bilərik . AbstractPhoneNumberValidatorGəlin bizim əcdadımız olacaq mücərrəd bir sinif elan edək 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;
       }
   }

}
Gördüyünüz kimi, biz bunu nəinki bəyan etdik, həm də daxili təbəqəni ona köçürdük PhoneNumber. Bununla belə, onun törəmə sinfində - PhoneNumberValidator- metodlardakı yerli siniflər 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);
           }
       }

       //...code валидации номера
   }
}
Varislik yolu ilə ünsiyyət sayəsində nəsil sinfi daxilində yerli siniflər əcdadın daxilindəki daxili sinifləri “görür”. Və nəhayət, son qrupa keçək :)

Daxili siniflər

Daxili sinif eyni xarici sinifdə (və ya onun nəslindən) elan edilmiş başqa bir daxili sinif tərəfindən miras qala bilər. Daxili siniflər haqqında mühazirədən velosiped nümunəmizdən istifadə edərək buna baxaq.
public class Bicycle {

   private String model;
   private int mawWeight;

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

   public void start() {
       System.out.println("Go!");
   }

   class Seat {

       public void up() {

           System.out.println("Сидение поднято выше!");
       }

       public void down() {

           System.out.println("Сидение опущено ниже!");
       }
   }

   class SportSeat extends Seat {

       //...methods
   }
}
Burada biz sinif daxilində Bicycledaxili sinif elan etdik Seat- oturacaq. Yarış oturacaqlarının xüsusi bir alt növü ondan miras qaldı - SportSeat. Bununla belə, biz ayrıca bir növ "yarış velosipedi" yarada və onu ayrıca bir sinifə qoya bilərik:
public class SportBicycle extends Bicycle {

   public SportBicycle(String model, int mawWeight) {
       super(model, mawWeight);
   }


   class SportSeat extends Seat {

       public void up() {

           System.out.println("Сидение поднято выше!");
       }

       public void down() {

           System.out.println("Сидение опущено ниже!");
       }
   }
}
Bu da mümkündür. Uşağın daxili təbəqəsi ( SportBicycle.SportSeat) əcdadın daxili təbəqələrini “görür” və onlardan miras ala bilər. Daxili siniflərdən miras bir çox vacib xüsusiyyətə malikdir! Əvvəlki iki nümunədə SportSeatdaxili var idi. SportSeatBəs onu daxili sinifdən miras qalan müntəzəm ictimai sinif etmək qərarına gəlsək nə olar Seat?
//ошибка! No inclosing instance of  type 'Bicycle' is in scope
class SportSeat extends Bicycle.Seat {

   public SportSeat() {

   }

   public void up() {

       System.out.println("Сидение поднято выше!");
   }

   public void down() {

       System.out.println("Сидение опущено ниже!");
   }
}
Bizdə xəta var! Bunun nə ilə əlaqəli olduğunu təxmin edə bilərsinizmi? :) Bu sadədir. Daxili sinif haqqında danışarkən Bicycle.Seatqeyd etdik ki, daxili sinifin konstruktoru xarici sinfin obyektinə istinad edir. Buna görə də, bir obyekt yaratmadan, Bicyclebir obyekt yarada bilməzsiniz Seat. Bəs yaradılış SportSeat? Konstruktorda xarici sinif obyektinə istinadın ötürülməsi üçün eyni daxili mexanizmə malik deyil Seat. Bununla belə, obyekt olmadan Bicycle, eynilə ilə olduğu kimi Seat, obyekt yarada bilmərik SportSeat. Buna görə də, bizim yalnız bir işimiz qalıb - SportSeatobyektə istinadı konstruktora Bicycleaçıq şəkildə ötürmək. Bunun necə edildiyi belədir:
class SportSeat extends Bicycle.Seat {

   public SportSeat(Bicycle bicycle) {

       bicycle.super();
   }

   public void up() {

       System.out.println("Сидение поднято выше!");
   }

   public void down() {

       System.out.println("Сидение опущено ниже!");
   }
}
Bunun üçün xüsusi bir sözdən istifadə edirik super(); . İndi obyekt yaratmaq istəsək SportSeat, heç nə bizə bunu etməyə mane olmayacaq:
public class Main {

   public static void main(String[] args) {

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

   }
}
Phew, mühazirə olduqca böyük oldu :) Amma siz çox yeni şeylər öyrəndiniz! İndi bir neçə problemi həll etməyin vaxtıdır! :)
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION