JavaRush /Java блогу /Random-KY /Java ичиндеги ички класстар же ички класстар

Java ичиндеги ички класстар же ички класстар

Группада жарыяланган
Салам! Бүгүн биз маанилүү теманы карай баштайбыз – Java тorнде уяланган класстар кантип иштейт. Англис тorнде алар уя класстар деп аталат. Java сизге башкалардын ичинде кээ бир класстарды түзүүгө мүмкүндүк берет:
class OuterClass {
    ...
    static class StaticNestedClass {
        ...
    }
    class InnerClass {
        ...
    }
}
Дал ушул класстар уя деп аталат. Алар 2 түргө бөлүнөт:
  1. Статикалык эмес уя класстар - статикалык эмес уя класстар. Алар дагы башка жол менен ички класстар деп аталат.
  2. Статикалык уя класстар - статикалык уя класстар.
Өз кезегинде, ички класстар эки өзгөчө түргө ээ. Ички класс жөн гана ички класс болушу мүмкүн экендигинен тышкары, ал дагы болушу мүмкүн:
  • жергorктүү класс
  • анонимдүү класс
Бир аз кыйынбы? :) Макул, бул жерде тактык үчүн диаграмма. Эгер күтүлбөгөн жерден түшүнбөсөңөр, лекция учурунда ага кайтып келиңиз! Уюшкан ички класстар - 2Бүгүнкү лекцияда ички класстар - ички класстар (алар дагы статикалык эмес уя класстар, статикалык эмес уя класстар) жөнүндө сүйлөшөбүз. Адашып калбашыңыз үчүн алар жалпы диаграммада атайын бөлүнгөн :) Келгиле, ачык суроодон баштайлы: эмне үчүн бул класстар “ички” деп аталат? Жооп абдан жөнөкөй: анткени алар башка класстардын ичинде түзүлгөн. Бул жерде бир мисал:
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!");
       }
   }
}
Бул жерде бизде класс бар Bicycle- велосипед. Анын 2 талаасы жана 1 ыкмасы бар - start(). Уюшкан ички класстар - 3Анын кадимки класстан айырмасы анын эки классы бар, анын codeу ичинде жазылган Bicycle– бул класстар HandleBar(руль) жана Seat(орун). Бул толук кандуу класстар: көрүп тургандай, алардын ар биринин өз ыкмалары бар. Ушул учурда сизде суроо пайда болушу мүмкүн: эмне үчүн биз бир классты экинчи класска койдук? Эмне үчүн аларды ички кылуу керек? Макул, программадагы руль жана отургуч үчүн өзүнчө класстар керек дейли. Бирок аларга уя салбашыңыз керек! Сиз кадимки сабактарды өткөрө аласыз. Мисалы, бул сыяктуу:
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!");
   }
}
Абдан жакшы суроо! Албетте, бизде техникалык чектөөлөр жок – биз муну ушундай кыла алабыз. Бул белгилүү бир программанын көз карашынан жана ошол программанын мааниси боюнча класстарды туура долбоорлоо жөнүндө көбүрөөк. Ички класстар - бул башка an object менен ажырагыс байланышта болгон программадагы белгилүү бир an objectти бөлүп көрсөтүү үчүн класстар. Руль, отургуч, педалдар велосипеддин компоненттери болуп саналат. Велосипедден бөлүнүп, алар эч кандай мааниге ээ эмес. Эгерде биз бул класстардын бардыгын өзүнчө ачык класстар кылсак, анда биздин программада, мисалы, төмөнкү code болушу мүмкүн:
public class Main {

   public static void main(String[] args) {
       HandleBar handleBar = new HandleBar();
       handleBar.right();
   }
}
Ммм... Бул codeдун маанисин түшүндүрүү да кыйын. Бизде кызыктай велосипед рулдору бар (бул эмне үчүн керек? Чынын айтсам, ою жок). Ал эми бул руль оңго... өзүнөн өзү, велосипедсиз... эмнегедир оңго бурулат. Рулдун маңызын велосипеддин маңызынан бөлүү менен биз программабыздын логикасын жоготтук. Ички классты колдонуу менен code такыр башкача көрүнөт:
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();
   }
}
Консолдук чыгаруу:

Сиденье поднято выше!
Поехали!
Руль влево!
Руль вправо!
Эмне болуп жатканы күтүлбөгөн жерден түшүнүктүү болуп калды! :) Велосипед an object курдук. Биз анын эки “предмети” – рулду жана отургучту жараттык. Ыңгайлуу болуу үчүн отургучту өйдө көтөрдүк – анан жөнөдүк: биз тоголонуп, керектүү жакка багыт алабыз! :) Бизге керек болгон ыкмалар керектүү an objectтерге чакырылат. Баары жөнөкөй жана ыңгайлуу. Бул мисалда рулду жана отургучту бөлүп көрсөтүү инкапсуляцияны жакшыртат (биз тиешелүү класстын ичинде велосипеддин бөлүктөрү жөнүндө маалыматтарды жашырып жатабыз) жана бизге кеңири абстракцияны түзүүгө мүмкүндүк берет. Эми дагы бир жагдайды карап көрөлү. Келгиле, биз велосипед жана тетиктер дүкөнүн моделдеген программа түзгүбүз келет дейли. Уюшкан ички класстар - 4Мындай кырдаалда биздин мурунку чечимибиз ишке ашпай калат. Тетиктер дүкөнүнүн чегинде велосипеддин ар бир жеке бөлүгү велосипеддин маңызынан башка да мааниге ээ. Мисалы, бизге "сатып алуучуга педалдарды сатуу", "жаңы орун сатып алуу" ж.б.у.с. Бул жерде ички класстарды колдонуу жаңылыштык болот - биздин жаңы программабыздын алкагында велосипеддин ар бир жеке бөлүгүнүн өзүнүн мааниси бар: ал велосипеддин маңызынан өзүнчө жана ага эч кандай байланышы жок. Эгерде сиз ички класстарды колдонушуңуз керекпи же бардык an objectтерди өзүнчө класстарга бөлүү керекпи деп ойлонуп жатсаңыз, ушуга көңүл бурушуңуз керек. Объектке багытталган программалоо эң сонун, анткени ал реалдуу дүйнө an objectтерин моделдештирүү үчүн жеңил кылат. Бул сиз ички класстарды колдонууну чечүүдө жетекчorк катары колдоно аласыз. Чыныгы дүкөндө тетиктер велосипеддерден өзүнчө - бул нормалдуу көрүнүш. Бул программаны иштеп чыгууда бул туура болот дегенди билдирет. Макул, биз "философияны" иреттеп алдык :) Эми ички класстардын маанилүү "техникалык" өзгөчөлүктөрү менен таанышалы. Бул жерде сиз сөзсүз эстеп, түшүнүшүңүз керек:
  1. Ички класстын an objectиси "тышкы" класстын an objectисиз жашай алbyte.

    Бул логикалуу: ошондуктан биз аны Seatички HandleBarкласстар кылып алдык, ошондуктан биздин программада ээси жок руль жана отургучтар бул жерде жана бул жерде пайда болбойт.

    Бул code түзүлбөйт:

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

    Мындан төмөнкү маанилүү өзгөчөлүк келип чыгат:

  2. Ички класстын an objectиси "сырткы" класстын өзгөрмөлөрүнө жетүү мүмкүнчүлүгүнө ээ.

    BicycleМисалы, биздин класска өзгөрмө кошолу int seatPostDiameter- отургучтун диаметри.

    Андан кийин ички класста биз отургучтун параметрин айтып бере турган Seatыкманы түзө алабыз :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);
           }
       }
    }

    Эми биз бул маалыматты биздин программадан ала алабыз:

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

    Консолдук чыгаруу:

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

    Көңүл буруу:жаңы өзгөрмө эң катуу өзгөрткүч менен жарыяланат - private. Анан дагы ички класстын мүмкүнчүлүгү бар!

  3. Ички класс an objectисин "тышкы" класстын статикалык методунда түзүү мүмкүн эмес.

    Бул ички класстардын дизайн өзгөчөлүктөрү менен түшүндүрүлөт. Ички класста параметрлери бар конструкторлор же жөн эле демейки конструктор болушу мүмкүн. Бирок буга карабастан, биз ички класстын an objectисин түзгөндө, ага "сырткы" класстын an objectисине шилтеме акырындык менен өтөт. Анткени, мындай an objectинин болушу милдеттүү шарт болуп саналат. Болбосо, биз ички класстын an objectтерин түзө албайбыз.

    Бирок сырткы класстын ыкмасы статикалык болсо, анда тышкы класстын an objectи такыр жок болушу мүмкүн! Бул ички класстын логикасы бузулат дегенди билдирет. Мындай кырдаалда компилятор ката кетирет:

    public static Seat createSeat() {
    
       //Bicycle.this cannot be referenced from a static context
       return new Seat();
    }
  4. Ички класс статикалык өзгөрмөлөрдү жана ыкмаларды камтышы мүмкүн эмес.

    Бул жерде логика бирдей: статикалык методдор жана өзгөрмөлөр an object жок болсо да бар жана чакырылышы мүмкүн.

    Бирок "тышкы" класстын an objectиси болбосо, биз ички класска кире албайбыз.

    Ачык карама-каршылык! Ошондуктан, ички класстарда статикалык өзгөрмөлөрдүн жана методдордун болушуна тыюу салынат.

    Компилятор аларды түзүүгө аракет кылып жатканда ката кетирет:

    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. Ички класстын an objectисин түзүүдө анын кирүү модификатору маанилүү роль ойнойт.

    Ички классты стандарттык кирүү модификаторлору менен белгилесе болот - public, private, protectedжана package private.

    Бул эмне үчүн маанилүү?

    Бул биздин программанын кайсы жеринде ички классты түзө аларыбызга таасир этет.

    Эгерде биздин класс Seatдеп жарыя кылынса public, биз анын an objectтерин башка класстарда түзө алабыз. Бир гана талап "тышкы" класстын an objectиси да болушу керек.

    Айтмакчы, биз муну бул жерде жасаганбыз:

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

    Биз ички класска оңой HandleBarкирдик Main.

    Эгерде биз ички классты деп жарыяласак private, биз "тышкы" класстын ичиндеги an objectтерди түзүүгө гана мүмкүнчүлүк алабыз.

    Биз мындан ары сырттан an object түзө Seatалбайбыз :

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

    Сиз логиканы түшүнсөңүз керек :)

  6. Ички класстар үчүн кирүү модификаторлору кадимки өзгөрмөлөрдөгүдөй иштешет.

    Модификатор protectedкласс өзгөрмөсүнө анын тукум класстарындагы жана бир пакеттеги класстардагы мүмкүнчүлүгүн камсыз кылат.

    Ошол эле protectedички класстар үчүн иштейт. protectedИчки класс an objectтери түзүлүшү мүмкүн:

    • "сырткы" класстын ичинде;
    • анын урпак класстарында;
    • ошол эле пакетте турган класстарда.

    Эгерде ички класста кирүү модификатору ( ) жок болсо package private, ички класстын an objectилерин түзүүгө болот

    • "сырткы" класстын ичинде;
    • бир пакетте турган класстарда.

    Модификаторлор менен көптөн бери таанышсыз, андыктан бул жерде эч кандай көйгөй болбойт.

Азырынча ушунусу менен :) Бирок эс алба! Ички уяча класстар - бул биз келечектеги сабактарда изилдөөнү уланта турган кенен тема. Эми сиз биздин курстан ички сабактар ​​боюнча лекцияны толуктай аласыз . Ал эми кийинки жолу биз статикалык уя класстар жөнүндө сүйлөшөбүз.
Комментарийлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION