JavaRush /Java блогы /Random-KK /Кірістірілген ішкі сыныптар немесе Java ішіндегі ішкі сын...

Кірістірілген ішкі сыныптар немесе Java ішіндегі ішкі сынып

Топта жарияланған
Сәлеметсіз бе! Бүгін біз маңызды тақырыпты қарастырамыз - Java тілінде кірістірілген сыныптар қалай жұмыс істейді. Ағылшын тілінде олар кірістірілген сыныптар деп аталады. Java басқалардың ішінде кейбір сыныптарды жасауға мүмкіндік береді:
class OuterClass {
    ...
    static class StaticNestedClass {
        ...
    }
    class InnerClass {
        ...
    }
}
Дәл осы кластар кірістірілген деп аталады. Олар 2 түрге бөлінеді:
  1. Статикалық емес кірістірілген сыныптар – статикалық емес кірістірілген сыныптар. Оларды басқаша ішкі сыныптар деп те атайды.
  2. Статикалық кірістірілген сыныптар – статикалық кірістірілген сыныптар.
Өз кезегінде, ішкі сыныптардың екі ерекше кіші түрі бар. Ішкі класс тек ішкі сынып болуы мүмкін фактісінен басқа, ол келесідей болуы мүмкін:
  • жергілікті сынып
  • анонимдік сынып
Кішкене қиын ба? :) Жарайды, түсінікті болу үшін мына диаграмма. Дәріс кезінде кенет шатасып қалсаңыз, оған қайта оралыңыз! Кірістірілген ішкі сыныптар - 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!");
   }
}
Өте жақсы сұрақ! Әрине, бізде техникалық шектеулер жоқ - біз мұны осылай жасай аламыз. Бұл белгілі бір бағдарлама тұрғысынан және сол бағдарламаның мағынасында сабақтарды дұрыс жобалау туралы көбірек. Ішкі сыныптар - бұл басқа нысанмен ажырамас байланысқан бағдарламадағы белгілі бір нысанды бөлектеуге арналған сыныптар. Руль, орындық, педальдар - велосипедтің құрамдас бөліктері. Велосипедтен бөлінген олар мағынасы жоқ. Егер біз осы сыныптардың барлығын бөлек жалпы сыныптарға айналдырсақ, біздің бағдарламамызда, мысалы, келесі 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ілерде шақырылады. Барлығы қарапайым және ыңғайлы. Бұл мысалда руль мен орынды бөлектеу инкапсуляцияны жақсартады (біз тиісті сыныптағы велосипед бөліктері туралы деректерді жасырамыз) және егжей-тегжейлі абстракция жасауға мүмкіндік береді. Енді басқа жағдайды қарастырайық. Велосипед пен бөлшектер дүкенін модельдейтін бағдарлама жасағымыз келеді делік. Кірістірілген ішкі сыныптар - 4Бұл жағдайда біздің алдыңғы шешіміміз сәтсіздікке ұшырайды. Бөлшектер дүкенінің шегінде велосипедтің әрбір жеке бөлігі велосипедтің мәнінен бөлек мағынаға ие. Мысалы, бізге «сатып алушыға педальдарды сату», «жаңа орын сатып алу» сияқты әдістер қажет болады. Мұнда ішкі сыныптарды пайдалану қате болар еді - біздің жаңа бағдарламамыздағы велосипедтің әрбір жеке бөлігінің өзіндік мәні бар: ол велосипедтің мәнінен бөлек және онымен ешқандай байланысы жоқ. Ішкі сыныптарды пайдалану немесе барлық нысандарды бөлек сыныптарға бөлу қажет пе деген сұрақ туындаса, осыған назар аудару керек. Нысанға бағытталған бағдарламалау өте жақсы, өйткені ол нақты әлем нысандарын модельдеуді жеңілдетеді. Бұл ішкі сыныптарды пайдалану-пайдалану туралы шешім қабылдағанда нұсқаулық ретінде пайдалануға болатын нәрсе. Нағыз дүкенде бөлшектер велосипедтерден бөлек - бұл қалыпты жағдай. Бұл бағдарламаны құрастыру кезінде бұл дұрыс болады дегенді білдіреді. Жарайды, біз «философияны» сұрыптадық :) Енді ішкі сыныптардың маңызды «техникалық» ерекшеліктерімен танысайық. Міне, сіз міндетті түрде есте сақтауыңыз және түсінуіңіз керек:
  1. Ішкі класстың an objectісі «сыртқы» сыныптың an objectісінсіз өмір сүре алмайды.

    Бұл қисынды: сондықтан біз бағдарламамызда иесіз рульдер мен орындықтар пайда болмас үшін оны Seatішкі сыныптар жасадық.HandleBar

    Бұл code компиляцияланбайды:

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

    Бұдан келесі маңызды қасиет шығады:

  2. Ішкі сыныптың нысаны «сыртқы» класстың айнымалыларына қол жеткізе алады.

    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ілерін жасай алмаймыз.

    Бірақ егер сыртқы сынып әдісі статикалық болса, онда сыртқы сынып нысаны мүлде болмауы мүмкін! Бұл ішкі таптың логикасы бұзылады деген сөз. Мұндай жағдайда компилятор қате жібереді:

    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ісі де болуы керек.

    Айтпақшы, біз мұны осында жасадық:

    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, біз тек «сыртқы» класс ішінде нысандарды жасауға рұқсат аламыз.

    Біз енді сырттан нысан жасай 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, ішкі сыныптың нысандарын жасауға болады

    • «сыртқы» сынып ішінде;
    • бір пакеттегі сыныптарда.

    Сіз модификаторлармен ұзақ уақыт бойы таныссыз, сондықтан мұнда ешқандай проблемалар болмайды.

Әзірше бәрі осы :) Бірақ босаңсуға болмайды! Ішкі кірістірілген сыныптар - біз алдағы сабақтарда зерттеуді жалғастыратын өте кең тақырып. Енді сіз біздің курстан ішкі сабақтар туралы дәріспен танысуға болады . Келесі жолы біз статикалық кірістірілген сыныптар туралы айтатын боламыз.
Пікірлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION