JavaRush /Java blogi /Random-UZ /Java-dagi ichki sinflar yoki ichki sinflar

Java-dagi ichki sinflar yoki ichki sinflar

Guruhda nashr etilgan
Salom! Bugun biz muhim mavzuni ko'rib chiqamiz - Java-da ichki o'rnatilgan sinflar qanday ishlaydi. Ingliz tilida ular ichki sinflar deb ataladi. Java sizga boshqalar ichida ba'zi sinflarni yaratishga imkon beradi:
class OuterClass {
    ...
    static class StaticNestedClass {
        ...
    }
    class InnerClass {
        ...
    }
}
Aynan shu sinflar ichki deb ataladi. Ular 2 turga bo'linadi:
  1. Statik bo'lmagan ichki o'rnatilgan sinflar - statik bo'lmagan ichki o'rnatilgan sinflar. Ular boshqa yo'l bilan ichki sinflar deb ham ataladi.
  2. Statik ichki o'rnatilgan sinflar - statik ichki o'rnatilgan sinflar.
O'z navbatida, ichki sinflar ikkita maxsus kichik tipga ega. Ichki sinf faqat ichki sinf bo'lishi mumkinligidan tashqari, u ham bo'lishi mumkin:
  • mahalliy sinf
  • anonim sinf
Biroz qiyinmi? :) Yaxshi, bu erda aniqlik uchun diagramma. Agar siz to'satdan sarosimaga tushsangiz, ma'ruza davomida unga qayting! Ichki ichki sinflar - 2Bugungi ma'ruzamizda biz ichki sinflar - ichki sinflar (ular ham statik bo'lmagan ichki sinflar, statik bo'lmagan ichki sinflar) haqida gapiramiz. Yo'qolmaslik uchun ular umumiy diagrammada alohida ta'kidlangan :) Keling, aniq savoldan boshlaylik: nima uchun bu sinflar "ichki" deb ataladi? Javob juda oddiy: chunki ular boshqa sinflar ichida yaratilgan. Mana bir misol:
public class Bicycle {

   private String model;
   private int weight;

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

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

   public class HandleBar {

       public void right() {
           System.out.println("Steering wheel to the right!");
       }

       public void left() {

           System.out.println("Steering wheel to the left!");
       }
   }

   public class Seat {

       public void up() {

           System.out.println("The seat is up!");
       }

       public void down() {

           System.out.println("The seat is down!");
       }
   }
}
Bu erda bizda sinf bor Bicycle- velosiped. Unda 2 ta maydon va 1 usul mavjud - start(). Ichki ichki sinflar - 3Uning oddiy sinfdan farqi shundaki, u ikkita sinfga ega, ularning kodi ichida yozilgan Bicycle- bular sinflar HandleBar(rul) va Seat(o'rindiq). Bular to'liq huquqli sinflar: ko'rib turganingizdek, ularning har biri o'z usullariga ega. Shu o'rinda sizda savol tug'ilishi mumkin: nega biz bir sinfni boshqasiga joylashtirdik? Nima uchun ularni ichki qilish kerak? OK, aytaylik, dasturda rul va o'rindiq uchun alohida sinflar kerak. Lekin siz ularni joylashtirishingiz shart emas! Bundan tashqari, siz muntazam darslar qilishingiz mumkin. Masalan, bu kabi:
public class HandleBar {
   public void right() {
       System.out.println("Steering wheel to the right!");
   }

   public void left() {

       System.out.println("Steering wheel left");
   }
}

public class Seat {

   public void up() {

       System.out.println("The seat is up!");
   }

   public void down() {

       System.out.println("The seat is down!");
   }
}
Juda yaxshi savol! Albatta, bizda texnik cheklovlar yo'q - biz buni shunday qilishimiz mumkin. Bu ko'proq ma'lum bir dastur nuqtai nazaridan va ushbu dasturning ma'nosida sinflarni to'g'ri loyihalash haqida. Ichki sinflar - bu boshqa ob'ekt bilan uzviy bog'liq bo'lgan dasturdagi ma'lum bir ob'ektni ajratib ko'rsatish uchun sinflar. Rulda, o'rindiq, pedallar velosipedning tarkibiy qismlaridir. Velosipeddan ajratilgan holda, ular mantiqiy emas. Agar biz ushbu sinflarning barchasini alohida umumiy sinflarga aylantirsak, bizning dasturimiz, masalan, quyidagi kodga ega bo'lishi mumkin:
public class Main {

   public static void main(String[] args) {
       HandleBar handleBar = new HandleBar();
       handleBar.right();
   }
}
Ummm... Ushbu kodning ma'nosini tushuntirish hatto qiyin. Bizda g'alati velosiped tutqichi bor (bu nima uchun kerak? Rostini aytsam, fikr yo'q). Bu rul esa o‘ngga buriladi... o‘z-o‘zidan, velosipedsiz... negadir. Rul g'ildiragining mohiyatini velosipedning mohiyatidan ajratib, biz dasturimizning mantiqiyligini yo'qotdik. Ichki sinfdan foydalanib, kod butunlay boshqacha ko'rinadi:
public class Main {

   public static void main(String[] args) {

       Bicycle peugeot = new Bicycle("Peugeot", 120);
       Bicycle.HandleBar handleBar = peugeot.new HandleBar();
       Bicycle.Seat seat = peugeot.new Seat();

       seat.up();
       peugeot.start();
       handleBar.left();
       handleBar.right();
   }
}
Konsol chiqishi:

Сиденье поднято выше!
Поехали!
Руль влево!
Руль вправо!
To'satdan sodir bo'lgan narsa mantiqiy edi! :) Biz velosiped ob'ektini yaratdik. Biz uning ikkita "sub'ekti" - rul va o'rindiqni yaratdik. Biz qulaylik uchun o'rindiqni baland ko'tardik - va biz jo'nadik: biz qayerga borishimiz kerak bo'lsa, biz aylanamiz va boshqaramiz! :) Bizga kerak bo'lgan usullar kerakli ob'ektlarda chaqiriladi. Hammasi oddiy va qulay. Ushbu misolda rul va o'rindiqni ajratib ko'rsatish inkapsulatsiyani kuchaytiradi (biz mos keladigan sinfdagi velosiped qismlari haqidagi ma'lumotlarni yashiramiz) va batafsilroq abstraktsiyani yaratishga imkon beradi. Endi boshqa vaziyatni ko'rib chiqaylik. Aytaylik, biz velosiped va ehtiyot qismlar do'konini modellashtiradigan dastur yaratmoqchimiz. Ichki ichki sinflar - 4Bunday vaziyatda bizning oldingi yechimimiz muvaffaqiyatsiz bo'ladi. Ehtiyot qismlar do'koni doirasida velosipedning har bir alohida qismi velosipedning mohiyatidan tashqari ma'noga ega. Masalan, bizga "xaridorga pedal sotish", "yangi o'rindiq sotib olish" va hokazo usullar kerak bo'ladi. Bu erda ichki sinflardan foydalanish xato bo'ladi - bizning yangi dasturimiz doirasida velosipedning har bir alohida qismi o'ziga xos ma'noga ega: u velosipedning mohiyatidan ajralib turadi va hech qanday tarzda unga bog'liq emas. Agar siz ichki sinflardan foydalanish kerakmi yoki barcha ob'ektlarni alohida sinflarga ajratish kerakmi, deb qiziqsangiz, bunga e'tibor berishingiz kerak. Ob'ektga yo'naltirilgan dasturlash juda yaxshi, chunki u haqiqiy dunyo ob'ektlarini modellashtirishni osonlashtiradi. Bu ichki sinflardan foydalanish to'g'risida qaror qabul qilishda qo'llanma sifatida foydalanishingiz mumkin. Haqiqiy do'konda qismlar velosipedlardan alohida - bu normal holat. Bu dasturni loyihalashda bu to'g'ri bo'lishini anglatadi. Yaxshi, biz "falsafa" ni saralab oldik :) Endi ichki sinflarning muhim "texnik" xususiyatlari bilan tanishamiz. Bu erda siz aniq eslab qolishingiz va tushunishingiz kerak bo'lgan narsa:
  1. Ichki sinf ob'ekti "tashqi" sinf ob'ektisiz mavjud bo'lolmaydi.

    Bu mantiqan to'g'ri: shuning uchun biz dasturimizda egasiz rul va o'rindiqlar ko'rinmasligi uchun uni Seatichki sinflarga aylantirdik.HandleBar

    Bu kod kompilyatsiya qilinmaydi:

    public static void main(String[] args) {
    
       HandleBar handleBar = new HandleBar();
    }

    Bundan quyidagi muhim xususiyat kelib chiqadi:

  2. Ichki sinf ob'ekti "tashqi" sinf o'zgaruvchilariga kirish huquqiga ega.

    BicycleMisol uchun, sinfimizga o'zgaruvchini qo'shamiz int seatPostDiameter- o'rindiq ustunining diametri.

    Keyin ichki sinfda biz o'rindiq parametrini aytib beradigan Seatusulni yaratishimiz mumkin :getSeatParam()

    public class Bicycle {
    
       private String model;
       private int weight;
    
       private int seatPostDiameter;
    
       public Bicycle(String model, int weight, int seatPostDiameter) {
           this.model = model;
           this.weight = weight;
           this.seatPostDiameter = seatPostDiameter;
    
       }
    
       public void start() {
           System.out.println("Go!");
       }
    
       public class Seat {
    
           public void up() {
    
               System.out.println("The seat is up!");
           }
    
           public void down() {
    
               System.out.println("The seat is down!");
           }
    
           public void getSeatParam() {
    
               System.out.println("Seat parameter: seatpost diameter = " + Bicycle.this.seatPostDiameter);
           }
       }
    }

    Va endi biz ushbu ma'lumotni dasturimizda olishimiz mumkin:

    public class Main {
    
       public static void main(String[] args) {
    
           Bicycle bicycle = new Bicycle("Peugeot", 120, 40);
           Bicycle.Seat seat = bicycle.new Seat();
    
           seat.getSeatParam();
       }
    }

    Konsol chiqishi:

    
    Параметр сиденья: диаметр подседельного штыря = 40

    Diqqat qilish:yangi o'zgaruvchi eng qattiq modifikator bilan e'lon qilinadi - private. Va hali ham ichki sinf kirish huquqiga ega!

  3. "Tashqi" sinfning statik usulida ichki sinf ob'ektini yaratib bo'lmaydi.

    Bu ichki sinflarning dizayn xususiyatlari bilan izohlanadi. Ichki sinfda parametrli konstruktorlar yoki oddiy konstruktor bo'lishi mumkin. Ammo bundan qat'iy nazar, biz ichki sinf ob'ektini yaratganimizda, unga "tashqi" sinf ob'ektiga havola jimgina yuboriladi. Axir, bunday ob'ektning mavjudligi zaruriy shartdir. Aks holda biz ichki sinf ob'ektlarini yarata olmaymiz.

    Ammo tashqi sinf usuli statik bo'lsa, tashqi sinf ob'ekti umuman mavjud bo'lmasligi mumkin! Demak, ichki sinfning mantig'i buziladi. Bunday vaziyatda kompilyator xatoga yo'l qo'yadi:

    public static Seat createSeat() {
    
       //Bicycle.this cannot be referenced from a static context
       return new Seat();
    }
  4. Ichki sinf statik o'zgaruvchilar va usullarni o'z ichiga olmaydi.

    Bu erda mantiq bir xil: statik usullar va o'zgaruvchilar ob'ekt bo'lmasa ham mavjud bo'lishi va chaqirilishi mumkin.

    Ammo "tashqi" sinf ob'ektisiz biz ichki sinfga kira olmaymiz.

    Aniq qarama-qarshilik! Shuning uchun ichki sinflarda statik o'zgaruvchilar va usullarning mavjudligi taqiqlanadi.

    Ularni yaratishga urinayotganda kompilyator xatoga yo'l qo'yadi:

    public class Bicycle {
    
       private int weight;
    
    
       public class Seat {
    
           //inner class cannot have static declarations
           public static void getSeatParam() {
    
               System.out.println("Seat parameter: seatpost diameter = " + Bicycle.this.seatPostDiameter);
           }
       }
    }
  5. Ichki sinf ob'ektini yaratishda uning kirish modifikatori muhim rol o'ynaydi.

    Ichki sinf standart kirish modifikatorlari bilan belgilanishi mumkin - public, private, protectedva package private.

    Nima uchun bu muhim?

    Bu bizning dasturimizda ichki sinfni yaratishimiz mumkin bo'lgan joyga ta'sir qiladi.

    Agar bizning sinfimiz Seatdeb e'lon qilingan bo'lsa public, biz uning ob'ektlarini istalgan boshqa sinfda yaratishimiz mumkin. Yagona talab shundaki, "tashqi" sinf ob'ekti ham mavjud bo'lishi kerak.

    Aytgancha, biz buni allaqachon bu erda qildik:

    public class Main {
    
       public static void main(String[] args) {
    
           Bicycle peugeot = new Bicycle("Peugeot", 120);
           Bicycle.HandleBar handleBar = peugeot.new HandleBar();
           Bicycle.Seat seat = peugeot.new Seat();
    
           seat.up();
           peugeot.start();
           handleBar.left();
           handleBar.right();
       }
    }

    HandleBarBiz dan ichki sinfga osongina kira oldik Main.

    Agar biz ichki sinfni deb e'lon qilsak private, biz faqat "tashqi" sinf ichidagi ob'ektlarni yaratish imkoniyatiga ega bo'lamiz.

    Biz endi tashqaridan ob'ekt yarata Seatolmaymiz :

    private class Seat {
    
       //methods
    }
    
    public class Main {
    
       public static void main(String[] args) {
    
           Bicycle bicycle = new Bicycle("Peugeot", 120, 40);
    
           //Bicycle.Seat has a private access in 'Bicycle'
           Bicycle.Seat seat = bicycle.new Seat();
       }
    }

    Siz mantiqni allaqachon tushungan bo'lsangiz kerak :)

  6. Ichki sinflar uchun kirish modifikatorlari oddiy o'zgaruvchilar bilan bir xil ishlaydi.

    Modifikator protectedsinf o'zgaruvchisiga uning avlod sinflarida va bir xil paketdagi sinflarda kirishni ta'minlaydi.

    Xuddi shu narsa protectedichki sinflar uchun ham ishlaydi. protectedIchki sinf ob'ektlari yaratilishi mumkin:

    • "tashqi" sinf ichida;
    • uning avlod sinflarida;
    • bir xil paketdagi sinflarda.

    Agar ichki sinfda kirish modifikatori ( ) bo'lmasa package private, ichki sinf ob'ektlari yaratilishi mumkin

    • "tashqi" sinf ichida;
    • bir xil paketdagi sinflarda.

    Siz modifikatorlar bilan uzoq vaqtdan beri tanishsiz, shuning uchun bu erda hech qanday muammo bo'lmaydi.

Hozircha hammasi :) Lekin tinchlanmang! Ichki o'rnatilgan sinflar - biz kelgusi darslarda o'rganishni davom ettiradigan juda keng mavzu. Endi siz bizning kursimizdagi ichki darslar bo'yicha ma'ruza bilan tanishishingiz mumkin . Va keyingi safar biz statik ichki sinflar haqida gapiramiz.
Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION