JavaRush /Java blogi /Random-UZ /Ichki sinflarning merosxo'rligi

Ichki sinflarning merosxo'rligi

Guruhda nashr etilgan
Salom! Bugun biz muhim mexanizmning ishlashini ko'rib chiqamiz - ichki sinflarda meros. Bilmayman, siz boshqa sinfdan o'rnatilgan sinfni meros qilib olishingiz kerak bo'lganda nima qilishingiz haqida hech o'ylab ko'rganmisiz. Agar yo'q bo'lsa, menga ishoning: bu vaziyat chalkash bo'lishi mumkin, chunki bu erda juda ko'p nuanslar mavjud:
  1. Biz ichki o'rnatilgan sinfni ba'zi sinfdan meros qilib olamizmi yoki ichki o'rnatilgan sinfdan boshqa sinfni meros qilib olamizmi?
  2. Voris/merosxo'r oddiy ommaviy sinfmi yoki u ham o'rnatilgan sinfmi?
  3. Va nihoyat, biz ushbu vaziyatlarning barchasida aynan qaysi turdagi ichki sinflardan foydalanamiz?
Agar siz bu savollarning barchasiga javob bersangiz, shunchalik ko'p javoblar bo'ladiki, sizning boshingiz aylanadi :) Ma'lumki, murakkab masalani hal qilish uchun uni oddiyroq qismlarga bo'lish kerak. Biz shunday qilamiz. Keling, ichki o'rnatilgan sinflarning har bir guruhini navbatma-navbat ikki nuqtai nazardan ko'rib chiqaylik: bu turdagi ichki o'rnatilgan sinfdan kim meros bo'lishi mumkin va u kimdan meros bo'lishi mumkin. Statik o'rnatilgan sinflardan boshlaylik.

Statik o'rnatilgan sinflar

Ichki sinflarning merosxo'rligiga misollar - 2Ularning meros qoidalari eng oddiy. Bu erda siz yuragingiz xohlagan deyarli hamma narsani qilishingiz mumkin. Statik ichki o'rnatilgan sinf quyidagilardan meros bo'lishi mumkin:
  • oddiy sinf
  • tashqi sinfda yoki uning ajdodlarida e'lon qilingan statik ichki sinf
Statik o'rnatilgan sinflar haqidagi ma'ruza misolini eslaylik.
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;
       }
   }
}
Keling, kodni o'zgartirib, statik ichki sinf Drawingva uning avlodini yaratishga harakat qilaylik - 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;
       }
   }
}
Ko'rib turganingizdek, muammo yo'q. Biz sinfni butunlay olib tashlaymiz Drawingva uni statik oʻrnatilgan sinf oʻrniga oddiy umumiy sinfga aylantira olamiz – hech narsa oʻzgarmaydi.
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 tartibga solingan. Statik o'rnatilgan sinfdan qanday sinflar meros bo'lishi mumkin? Deyarli har qanday! Ichki / muntazam, statik / statik bo'lmagan - bu muhim emas. Bu erda biz ichki sinfni Boeing737Drawingstatik o'rnatilgan sinfdan meros qilib olamiz 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;
       }
   }
}
Boeing737DrawingSiz shunday misol yaratishingiz mumkin:
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());

   }

}
Bizning sinfimiz Boeing737Drawingstatik sinfdan meros bo'lsa-da, uning o'zi statik emas! Shuning uchun u har doim tashqi sinfning namunasiga muhtoj bo'ladi. Biz sinfni Boeing737Drawingsinfdan olib tashlashimiz Boeing737va uni oddiy sinfga aylantirishimiz mumkin. Hech narsa o'zgarmaydi - u statik nesteddan ham meros bo'lishi mumkin 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;

}
Faqatgina muhim nuqta: bu holda biz statik o'zgaruvchini maxPassengersCountommaviy qilishimiz kerak. Agar u shaxsiy bo'lib qolsa, oddiy umumiy sinf unga kira olmaydi. Biz statik sinflarni saralab oldik! :) Endi ichki sinflarga o'tamiz. Esingizda bo'lsa, ularning 3 turi mavjud: oddiygina ichki sinflar, mahalliy sinflar va anonim ichki sinflar. Ichki sinflarning merosxo'rligiga misollar - 3Yana oddiydan murakkabga o'tamiz :)

Anonim ichki sinflar

Anonim ichki sinf boshqa sinfdan meros bo'lolmaydi. Boshqa hech qanday sinf anonim sinfdan meros bo'la olmaydi. Bu oddiyroq bo'lishi mumkin emas! :)

Mahalliy sinflar

Mahalliy sinflar (agar unutgan bo'lsangiz) boshqa sinfning kod blokida e'lon qilinadi. Ko'pincha - bu tashqi sinfning ba'zi usullari ichida. Mahalliy sinfdan faqat bir xil usul (yoki blok) ichidagi boshqa mahalliy sinflar meros bo'lishi mantiqan to'g'ri. Mana bir misol:
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 bizning mahalliy sinflar haqidagi ma'ruzamizning kodi. Raqamni tekshirish sinfida bizda mahalliy sinf PhoneNumber- telefon raqami mavjud. Agar bizning maqsadlarimiz uchun undan ikkita alohida ob'ektni, masalan, mobil telefon raqami va shahar telefon raqamini ajratib olishimiz kerak bo'lsa, biz buni faqat bir xil usulda amalga oshirishimiz mumkin. Sababi oddiy: mahalliy sinf doirasi e'lon qilingan usul (blok) ichida. Shuning uchun biz uni qandaydir tarzda tashqi tomondan (shu jumladan meros uchun) ishlata olmaymiz. Biroq, mahalliy sinfning o'zi meros olish uchun kengroq imkoniyatlarga ega! Mahalliy sinf quyidagilardan meros bo'lishi mumkin:
  1. Oddiy sinf.
  2. Mahalliy sinf yoki uning ajdodlarida bir xil sinfda e'lon qilingan ichki sinf.
  3. Xuddi shu usulda (blokda) e'lon qilingan boshqa mahalliy sinfdan.
Birinchi va uchinchi nuqtalar aniq ko'rinadi, lekin ikkinchisi biroz chalkash :/ Keling, ikkita misolni ko'rib chiqaylik. 1-misol - "mahalliy sinf bilan bir xil sinfda e'lon qilingan ichki sinfdan mahalliy sinfni meros qilib olish":
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 валидации номера
   }
}
Bu erda biz sinfni PhoneNumbermetoddan chiqarib tashladik validatePhoneNumber()va uni mahalliy o'rniga ichki qildik. Bu bizning 2 mahalliy sinfimizni undan meros qilib olishimizga to'sqinlik qilmaydi. 2-misol - "... yoki bu sinfning ajdodlarida." Bu erda u yanada qiziqarli bo'ladi. Biz uni PhoneNumbermeros zanjiri bo'yicha yanada yuqoriga ko'tarishimiz mumkin. Keling, AbstractPhoneNumberValidatorbizning ajdodimiz bo'ladigan mavhum sinfni e'lon qilaylik 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;
       }
   }

}
Ko'rib turganingizdek, biz nafaqat e'lon qildik, balki ichki sinfni ham unga ko'chirdik PhoneNumber. Biroq, uning avlod sinfida - PhoneNumberValidator- usullardagi mahalliy sinflar dan meros bo'lishi mumkin 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 валидации номера
   }
}
Meros orqali bog'lanish tufayli avlod sinfidagi mahalliy sinflar ajdod ichidagi ichki sinflarni "ko'radi". Va nihoyat, oxirgi guruhga o'tamiz :)

Ichki sinflar

Ichki sinf bir xil tashqi sinfda (yoki uning avlodida) e'lon qilingan boshqa ichki sinf tomonidan meros qilib olinishi mumkin. Keling, buni ichki sinflar haqidagi ma'ruzadagi velosiped misolimizdan foydalanib ko'rib chiqaylik.
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
   }
}
Bu erda biz sinf ichidagi Bicycleichki sinfni e'lon qildik Seat- o'rindiq. Undan poyga o'rindiqlarining maxsus kichik turi meros bo'lib o'tdi - SportSeat. Biroq, biz "poyga velosipedlari" ning alohida turini yaratib, uni alohida sinfga qo'yishimiz mumkin:
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 ham mumkin. Bolaning ichki sinfi ( SportBicycle.SportSeat) ajdodlarning ichki sinflarini "ko'radi" va ulardan meros olishi mumkin. Ichki sinflardan meros bitta muhim xususiyatga ega! Oldingi ikkita misolda bizda SportSeatichki bor edi. SportSeatAmmo agar biz uni ichki sinfdan meros bo'lib qolgan oddiy jamoat sinfiga aylantirishga qaror qilsak nima bo'ladi 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("Сидение опущено ниже!");
   }
}
Bizda xatolik yuz berdi! Bu nima bilan bog'liqligini taxmin qila olasizmi? :) Hammasi oddiy. Biz ichki sinf haqida gapirganda Bicycle.Seat, biz ichki sinf konstruktori tashqi sinf ob'ektiga havolani bilvosita o'tkazishini eslatib o'tdik. Shuning uchun, ob'ekt yaratmasdan, Bicycleob'ektni yarata olmaysiz Seat. Yaratilish haqida nima deyish mumkin SportSeat? U konstruktordagi tashqi sinf ob'ektiga havolani bilvosita o'tkazish uchun o'rnatilgan mexanizmga ega emas Seat. Biroq, ob'ektsiz Bicycle, xuddi bilan bo'lgani kabi Seat, biz ob'ektni yarata olmaymiz SportSeat. Shuning uchun bizda faqat bitta narsa qoldi - SportSeatob'ektga havolani konstruktorga Bicycleaniq o'tkazish. Bu qanday amalga oshiriladi:
class SportSeat extends Bicycle.Seat {

   public SportSeat(Bicycle bicycle) {

       bicycle.super();
   }

   public void up() {

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

   public void down() {

       System.out.println("Сидение опущено ниже!");
   }
}
Buning uchun biz maxsus so'zdan foydalanamiz super(); Endi, agar biz ob'ekt yaratmoqchi bo'lsak SportSeat, buni qilishimizga hech narsa to'sqinlik qilmaydi:
public class Main {

   public static void main(String[] args) {

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

   }
}
Oh, ma'ruza juda katta bo'lib chiqdi :) Lekin siz juda ko'p yangi narsalarni o'rgandingiz! Endi bir nechta muammolarni hal qilish vaqti keldi! :)
Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION