JavaRush /Java Blog /Random-TL /Mga nested na panloob na klase o Inner Class sa Java

Mga nested na panloob na klase o Inner Class sa Java

Nai-publish sa grupo
Kamusta! Ngayon ay magsisimula tayong tumingin sa isang mahalagang paksa - kung paano gumagana ang mga nested na klase sa Java. Sa Ingles sila ay tinatawag na nested classes. Pinapayagan ka ng Java na lumikha ng ilang mga klase sa loob ng iba:
class OuterClass {
    ...
    static class StaticNestedClass {
        ...
    }
    class InnerClass {
        ...
    }
}
Ito ang mga klase na tinatawag na nested. Nahahati sila sa 2 uri:
  1. Non-static na nested na klase - non-static na nested na klase. Tinatawag din silang mga panloob na klase sa ibang paraan.
  2. Mga static na nested na klase - mga static na nested na klase.
Sa turn, ang mga panloob na klase ay may dalawang espesyal na subtype. Bukod sa katotohanan na ang isang panloob na klase ay maaaring isang panloob na klase lamang, maaari rin itong maging:
  • lokal na klase
  • anonymous na klase
Medyo mahirap? :) Okay lang, narito ang isang diagram para sa kalinawan. Bumalik dito sa panahon ng panayam kung bigla kang nalilito! Mga nested na panloob na klase - 2Sa lecture ngayon ay pag-uusapan natin ang tungkol sa mga Inner class - mga panloob na klase (mga non static nested class din sila, non-static nested classes). Espesyal na naka-highlight ang mga ito sa pangkalahatang diagram upang hindi ka maligaw :) Magsimula tayo sa malinaw na tanong: bakit tinawag na "internal" ang mga klase na ito? Ang sagot ay medyo simple: dahil sila ay nilikha sa loob ng ibang mga klase. Narito ang isang halimbawa:
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!");
       }
   }
}
Dito kami may klase Bicycle- bisikleta. Mayroon itong 2 field at 1 method - start(). Mga nested na panloob na klase - 3Ang pagkakaiba nito sa isang regular na klase ay mayroon itong dalawang klase, ang code nito ay nakasulat sa loob Bicycle- ito ang mga klase HandleBar(manibela) at Seat(upuan). Ang mga ito ay ganap na mga klase: tulad ng nakikita mo, bawat isa sa kanila ay may sariling mga pamamaraan. Sa puntong ito, maaaring may tanong ka: bakit namin inilagay ang isang klase sa loob ng isa pa? Bakit ginagawa silang panloob? Okay, sabihin nating kailangan natin ng magkakahiwalay na klase para sa manibela at upuan sa programa. Ngunit hindi mo kailangang pugad sila! Maaari kang gumawa ng mga regular na klase. Halimbawa, tulad nito:
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!");
   }
}
Napakagandang tanong! Siyempre, wala kaming teknikal na limitasyon - magagawa namin ito sa ganitong paraan. Ito ay higit pa tungkol sa pagdidisenyo ng mga klase nang tama mula sa punto ng view ng isang partikular na programa at sa kahulugan ng programang iyon. Ang mga panloob na klase ay mga klase para sa pag-highlight ng isang partikular na entity sa isang programa na hindi mapaghihiwalay na nauugnay sa isa pang entity. Ang manibela, upuan, mga pedal ay ang mga bahagi ng isang bisikleta. Hiwalay sa bisikleta, wala silang katuturan. Kung ginawa naming magkahiwalay ang lahat ng klaseng ito sa mga pampublikong klase, maaaring magkaroon ang aming programa, halimbawa, ng sumusunod na code:
public class Main {

   public static void main(String[] args) {
       HandleBar handleBar = new HandleBar();
       handleBar.right();
   }
}
Ummm... Mahirap pa ngang ipaliwanag ang kahulugan ng code na ito. Mayroon kaming kakaibang manibela ng bisikleta (bakit kailangan ito? Walang ideya, sa totoo lang). At ang manibela na ito ay lumiliko sa kanan... sa sarili nitong, walang bisikleta... sa ilang kadahilanan. Sa pamamagitan ng paghihiwalay ng kakanyahan ng manibela mula sa kakanyahan ng bisikleta, nawala namin ang lohika ng aming programa. Gamit ang isang panloob na klase, ang code ay mukhang ganap na naiiba:
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();
   }
}
Output ng console:

Сиденье поднято выше!
Поехали!
Руль влево!
Руль вправо!
Biglang nagkaroon ng sense ang mga nangyayari! :) Nakagawa kami ng bagay sa bisikleta. Gumawa kami ng dalawa sa mga "subobject" nito - ang manibela at ang upuan. Itinaas namin ang upuan nang mas mataas para sa kaginhawahan - at umalis na kami: gumulong kami at nagtutulak kung saan namin kailangan pumunta! :) Ang mga pamamaraan na kailangan namin ay tinatawag sa mga kinakailangang bagay. Ang lahat ay simple at maginhawa. Sa halimbawang ito, ang pag-highlight sa mga handlebar at upuan ay nagpapahusay ng encapsulation (nagtatago kami ng data tungkol sa mga bahagi ng bisikleta sa loob ng kaukulang klase), at nagbibigay-daan sa amin na lumikha ng mas detalyadong abstraction. Ngayon tingnan natin ang isa pang sitwasyon. Sabihin nating gusto nating gumawa ng program na nagmomodelo ng tindahan ng bisikleta at mga piyesa. Mga nested na panloob na klase - 4Sa ganitong sitwasyon, mabibigo ang dati nating solusyon. Sa loob ng mga hangganan ng isang tindahan ng mga piyesa, ang bawat indibidwal na bahagi ng isang bike ay may kahulugan kahit na bukod sa esensya ng bike. Halimbawa, kakailanganin namin ng mga pamamaraan tulad ng "magbenta ng mga pedal sa isang mamimili", "bumili ng bagong upuan", atbp. Magiging isang pagkakamali na gumamit ng mga panloob na klase dito - bawat indibidwal na bahagi ng bisikleta sa loob ng aming bagong programa ay may sariling kahulugan: ito ay hiwalay sa esensya ng bisikleta, at sa anumang paraan ay hindi nakatali dito. Ito ang dapat mong bigyang pansin kung iniisip mo kung kailangan mong gumamit ng mga panloob na klase, o paghiwalayin ang lahat ng entity sa magkakahiwalay na klase. Mahusay ang Object-oriented programming dahil ginagawa nitong madali ang pag-modelo ng mga real-world na entity. Ito ang maaari mong gamitin bilang gabay kapag nagpapasya kung gagamit ng mga panloob na klase. Sa isang tunay na tindahan, ang mga bahagi ay hiwalay sa mga bisikleta - ito ay normal. Nangangahulugan ito na ito ay magiging tama kapag nagdidisenyo ng isang programa. Okay, inayos na namin ang "pilosopiya" :) Ngayon ay kilalanin natin ang mahahalagang "teknikal" na mga tampok ng mga panloob na klase. Narito ang tiyak na kailangan mong tandaan at maunawaan:
  1. Ang isang bagay ng isang panloob na klase ay hindi maaaring umiral nang walang isang bagay ng isang "panlabas" na klase.

    Ito ay lohikal: kaya ginawa namin itong mga Seatpanloob HandleBarna klase, upang ang mga manibela at upuan na walang may-ari ay hindi lumabas dito at doon sa aming programa.

    Ang code na ito ay hindi mag-compile:

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

    Ang sumusunod na mahalagang tampok ay sumusunod mula dito:

  2. Ang isang bagay ng isang panloob na klase ay may access sa mga variable ng "panlabas" na klase.

    Halimbawa, magdagdag tayo Bicycleng variable sa ating klase int seatPostDiameter- ang diameter ng seatpost.

    Pagkatapos sa panloob na klase Seatmaaari kaming lumikha ng isang pamamaraan getSeatParam()na magsasabi sa amin ng parameter ng upuan:

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

    At ngayon ay makukuha natin ang impormasyong ito sa ating programa:

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

    Output ng console:

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

    Bigyang-pansin:ang bagong variable ay ipinahayag na may pinakamahigpit na modifier - private. At mayroon pa ring access ang panloob na klase!

  3. Ang isang bagay sa loob ng klase ay hindi maaaring gawin sa isang static na pamamaraan ng isang "panlabas" na klase.

    Ito ay ipinaliwanag ng mga tampok ng disenyo ng mga panloob na klase. Ang isang panloob na klase ay maaaring magkaroon ng mga konstruktor na may mga parameter o isang default na konstruktor lamang. Ngunit anuman ito, kapag lumikha tayo ng isang bagay ng panloob na klase, ang isang sanggunian sa isang bagay ng "panlabas" na klase ay tahimik na ipinapasa dito. Pagkatapos ng lahat, ang pagkakaroon ng naturang bagay ay isang paunang kinakailangan. Kung hindi, hindi tayo makakalikha ng mga bagay ng panloob na klase.

    Ngunit kung ang pamamaraan ng panlabas na klase ay static, kung gayon ang bagay na panlabas na klase ay maaaring hindi umiiral! Nangangahulugan ito na ang lohika ng inner class ay masisira. Sa ganoong sitwasyon, ang compiler ay magtapon ng isang error:

    public static Seat createSeat() {
    
       //Bicycle.this cannot be referenced from a static context
       return new Seat();
    }
  4. Ang isang panloob na klase ay hindi maaaring maglaman ng mga static na variable at pamamaraan.

    Ang lohika dito ay pareho: ang mga static na pamamaraan at mga variable ay maaaring umiral at matatawag kahit na walang object.

    Ngunit kung walang object ng "outer" class, hindi tayo magkakaroon ng access sa inner class.

    Isang halatang kontradiksyon! Samakatuwid, ang pagkakaroon ng mga static na variable at pamamaraan sa mga panloob na klase ay ipinagbabawal.

    Magtatapon ng error ang compiler kapag sinusubukang likhain ang mga ito:

    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. Kapag gumagawa ng isang bagay sa loob ng klase, ang access modifier nito ay may mahalagang papel.

    Ang isang panloob na klase ay maaaring tukuyin ng mga karaniwang access modifier - public, private, protectedat package private.

    Bakit ito mahalaga?

    Nakakaapekto ito kung saan sa aming programa maaari naming i-instantiate ang panloob na klase.

    Kung ang aming klase Seatay idineklara bilang public, maaari kaming lumikha ng mga bagay nito sa anumang ibang klase. Ang tanging kinakailangan ay ang isang bagay ng "panlabas" na klase ay dapat ding umiral.

    Sa pamamagitan ng paraan, nagawa na namin ito dito:

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

    Madali naming na-access ang inner class HandleBarmula sa Main.

    Kung idedeklara namin ang inner class bilang private, magkakaroon lang kami ng access sa paglikha ng mga bagay sa loob ng "outer" class.

    SeatHindi na kami makakagawa ng object mula sa labas:

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

    Malamang naiintindihan mo na ang logic :)

  6. Ang mga modifier ng access para sa mga panloob na klase ay gumagana katulad ng para sa mga regular na variable.

    Nagbibigay ang modifier protectedng access sa isang variable ng klase sa mga descendant na klase nito at sa mga klase na nasa parehong package.

    Ang parehong protectedgumagana para sa mga panloob na klase. Maaaring malikha ang mga bagay protectedsa loob ng klase :

    • sa loob ng "panlabas" na klase;
    • sa mga descendant classes nito;
    • sa mga klase na nasa parehong pakete.

    Kung ang inner class ay walang access modifier ( package private), ang mga object ng inner class ay maaaring malikha

    • sa loob ng "panlabas" na klase;
    • sa mga klase na nasa parehong pakete.

    Matagal ka nang pamilyar sa mga modifier, kaya walang magiging problema dito.

Sa ngayon lang yan :) Pero wag kang mag relax! Ang mga internal na nested na klase ay isang medyo malawak na paksa na patuloy nating tuklasin sa mga susunod na aralin. Ngayon ay maaari ka nang mag-ayos sa lecture sa mga panloob na klase mula sa aming kurso. At sa susunod na pag-uusapan natin ang tungkol sa mga static na nested na klase.
Mga komento
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION