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:
- Biz ichki o'rnatilgan sinfni ba'zi sinfdan meros qilib olamizmi yoki ichki o'rnatilgan sinfdan boshqa sinfni meros qilib olamizmi?
- Voris/merosxo'r oddiy ommaviy sinfmi yoki u ham o'rnatilgan sinfmi?
- Va nihoyat, biz ushbu vaziyatlarning barchasida aynan qaysi turdagi ichki sinflardan foydalanamiz?
Statik o'rnatilgan sinflar
Ularning 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
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 Drawing
va 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 Drawing
va 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 Boeing737Drawing
statik 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;
}
}
}
Boeing737Drawing
Siz 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 Boeing737Drawing
statik sinfdan meros bo'lsa-da, uning o'zi statik emas! Shuning uchun u har doim tashqi sinfning namunasiga muhtoj bo'ladi. Biz sinfni Boeing737Drawing
sinfdan olib tashlashimiz Boeing737
va 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 maxPassengersCount
ommaviy 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. Yana 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:
- Oddiy sinf.
- Mahalliy sinf yoki uning ajdodlarida bir xil sinfda e'lon qilingan ichki sinf.
- Xuddi shu usulda (blokda) e'lon qilingan boshqa mahalliy sinfdan.
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 PhoneNumber
metoddan 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 PhoneNumber
meros zanjiri bo'yicha yanada yuqoriga ko'tarishimiz mumkin. Keling, AbstractPhoneNumberValidator
bizning 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 Bicycle
ichki 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 SportSeat
ichki bor edi. SportSeat
Ammo 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, Bicycle
ob'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 - SportSeat
ob'ektga havolani konstruktorga Bicycle
aniq 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! :)
GO TO FULL VERSION