CodeGym /Java-blogg /Tilfeldig /Nestede indre klasser
John Squirrels
Nivå
San Francisco

Nestede indre klasser

Publisert i gruppen
Hei! I dag skal vi ta opp et viktig emne - hvordan nestede klasser fungerer i Java. Java lar deg lage klasser i en annen klasse:

class OuterClass {
    ...
    static class StaticNestedClass {
        ...
    }
    class InnerClass {
        ...
    }
}
Disse interne klassene kalles nestede. De er delt inn i 2 typer:
  1. Ikke-statiske nestede klasser. Disse kalles også indre klasser.
  2. Statiske nestede klasser.
På sin side har indre klasser to distinkte underkategorier. I tillegg til at en indre klasse ganske enkelt er en indre klasse, kan den også være:
  • en lokal klasse
  • en anonym klasse
Forvirret? :) Det er ok. Her er et diagram for klarhet. Kom tilbake til det i løpet av leksjonen hvis du plutselig finner deg selv forvirret! Nestede indre klasser - 2I dagens leksjon vil vi diskutere indre klasser (også kjent som ikke-statiske nestede klasser). De er spesielt fremhevet i det overordnede diagrammet slik at du ikke går deg vill :) La oss starte med det åpenbare spørsmålet: hvorfor kalles de "indre" klasser? Svaret er ganske enkelt: fordi de er laget i andre klasser. Her er et eksempel:

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("Let's go!");
   }

   public class Handlebar {

       public void right() {
           System.out.println("Steer right!");
       }

       public void left() {

           System.out.println("Steer left!");
       }
   }

   public class Seat {
      
       public void up() {

           System.out.println("Seat up!");
       }
      
       public void down() {

           System.out.println("Seat down!");
       }
   }
}
Her har vi Bicycleklassen. Den har 2 felt og 1 metode: start(). Nestede indre klasser - 3Den skiller seg fra en vanlig klasse ved at den inneholder to klasser: Handlebarog Seat. Koden deres er skrevet inne i Bicycleklassen. Dette er fullverdige klasser: som du kan se, har hver av dem sine egne metoder. På dette tidspunktet har du kanskje et spørsmål: hvorfor i all verden skulle vi sette en klasse inn i en annen? Hvorfor gjøre dem til indre klasser? Vel, anta at vi trenger separate klasser for konseptene styre og sete i programmet vårt. Det er selvfølgelig ikke nødvendig for oss å lage dem nestet! Vi kan lage vanlige klasser. For eksempel slik:

public class Handlebar {
   public void right() {
       System.out.println("Steer right!");
   }

   public void left() {

       System.out.println("Steer left");
   }
}

public class Seat {

   public void up() {

       System.out.println("Seat up!");
   }

   public void down() {

       System.out.println("Seat down!");
   }
}
Veldig godt spørsmål! Selvfølgelig er vi ikke begrenset av teknologien. Å gjøre det er absolutt et alternativ. Her er det viktige mer riktig utforming av klassene fra perspektivet til et spesifikt program og dets formål. Indre klasser er for å skille ut en enhet som er uløselig forbundet med en annen enhet. Styre, seter og pedaler er komponenter i en sykkel. Atskilt fra sykkelen gir de ikke mye mening. Hvis vi gjorde alle disse konseptene separate offentlige klasser, ville vi hatt koden slik i programmet vårt:

public class Main {

   public static void main(String[] args) {
       Handlebar handlebar = new Handlebar();
       handlebar.right();
   }
}
Hmm... Betydningen av denne koden er til og med vanskelig å forklare. Vi har et vagt styre (hvorfor er det nødvendig? Ingen anelse, for å være ærlig). Og dette håndtaket svinger til høyre... helt av seg selv, uten sykkel... av en eller annen grunn. Ved å skille konseptet med styret fra konseptet med sykkelen, mistet vi litt logikk i programmet vårt. Ved å bruke en indre klasse ser koden veldig annerledes ut:

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

Seat up! 
Let's go! 
Steer left! 
Steer right!
Nå gir det vi ser plutselig mening! :) Vi laget et sykkelobjekt. Vi laget to "delobjekter" for sykkel - et styre og et sete. Vi hevet setet for komfort og av gårde: tråkket og styrte etter behov! :) Metodene vi trenger kalles på de aktuelle objektene. Det hele er enkelt og praktisk. I dette eksemplet forbedrer det å skille ut styret og setet innkapslingen (vi skjuler data om sykkeldelene i den aktuelle klassen) og lar oss lage en mer detaljert abstraksjon. La oss nå se på en annen situasjon. Anta at vi vil lage et program som simulerer en sykkelbutikk og reservedeler til sykler. Nestede indre klasser - 4I denne situasjonen vil ikke vår forrige løsning fungere. I en sykkelbutikk gir hver enkelt sykkeldel mening selv når den er adskilt fra en sykkel. For eksempel vil vi trenge metoder som "selge pedaler til en kunde", "kjøpe et nytt sete" osv. Det ville være feil å bruke indre klasser her — hver enkelt sykkeldel i vårt nye program har betydning som står på sin egen: den kan skilles fra konseptet med en sykkel. Det er nettopp dette du må være oppmerksom på hvis du lurer på om du bør bruke indre klasser eller organisere alle enhetene som separate klasser. Objektorientert programmering er bra ved at det gjør det enkelt å modellere virkelige enheter. Dette kan være ditt veiledende prinsipp når du bestemmer deg for om du skal bruke indre klasser. I en ekte butikk, reservedeler er atskilt fra sykler — dette er greit. Dette betyr at det også er greit når man designer et program. Ok, vi har funnet ut "filosofien" :) La oss nå bli kjent med viktige "tekniske" trekk ved indre klasser. Her er det du definitivt trenger å huske og forstå:
  1. Et objekt av en indre klasse kan ikke eksistere uten et objekt av en ytre klasse.

    Dette er fornuftig: dette er grunnen til at vi laget Seatog Handlebarindre klasser i programmet vårt — slik at vi ikke ender opp med foreldreløse styre og seter.

    Denne koden kompilerer ikke:

    
    public static void main(String[] args) {
    
       Handlebar handlebar = new Handlebar();
    }
    

    En annen viktig funksjon følger av dette:

  2. Et objekt av en indre klasse har tilgang til variablene til den ytre klassen.

    La oss for eksempel legge til en int seatPostDiametervariabel (som representerer diameteren på setepinnen) til Bicycleklassen vår.

    Så i den Seatindre klassen kan vi lage en displaySeatProperties()metode som viser seteegenskapene:

    
    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("Let's go!");
       }
    
       public class Seat {
    
           public void up() {
    
               System.out.println("Seat up!");
           }
    
           public void down() {
    
               System.out.println("Seat down!");
           }
    
           public void displaySeatProperties() {
    
               System.out.println("Seat properties: seatpost diameter = " + Bicycle.this.seatPostDiameter);
           }
       }
    }
    

    Og nå kan vi vise denne informasjonen i programmet vårt:

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

    Konsoll utgang:

    
    Seat properties: seatpost diameter = 40
    

    Merk:den nye variabelen er deklarert med den strengeste tilgangsmodifikatoren ( private). Og fortsatt har den indre klassen tilgang!

  3. Et objekt av en indre klasse kan ikke opprettes i en statisk metode for en ytre klasse.

    Dette forklares av de spesifikke egenskapene til hvordan indre klasser er organisert. En indre klasse kan ha konstruktører med parametere, eller bare standard konstruktør. Men uansett, når vi lager et objekt av en indre klasse, overføres en referanse til objektet til den ytre klassen usynlig til det opprettede objektet til den indre klassen. Tross alt er tilstedeværelsen av en slik objektreferanse et absolutt krav. Ellers vil vi ikke være i stand til å lage objekter av den indre klassen.

    Men hvis en metode for den ytre klassen er statisk, så har vi kanskje ikke et objekt av den ytre klassen! Og dette ville være et brudd på logikken i hvordan en indre klasse fungerer. I denne situasjonen vil kompilatoren generere en feil:

    
    public static Seat createSeat() {
      
       // Bicycle.this cannot be referenced from a static context
       return new Seat();
    }
    
  4. En indre klasse kan ikke inneholde statiske variabler og metoder.

    Logikken er den samme: statiske metoder og variabler kan eksistere og kalles eller refereres til selv i fravær av et objekt.

    Men uten et objekt fra den ytre klassen, vil vi ikke ha tilgang til den indre klassen.

    En klar motsetning! Dette er grunnen til at statiske variabler og metoder ikke er tillatt i indre klasser.

    Kompilatoren vil generere en feil hvis du prøver å lage dem:

    
    public class Bicycle {
    
       private int weight;
    
    
       public class Seat {
          
           // An inner class cannot have static declarations
           public static void displaySeatProperties() {
    
               System.out.println("Seat properties: seatpost diameter = " + Bicycle.this.seatPostDiameter);
           }
       }
    }
    
  5. Når du oppretter et objekt av en indre klasse, er tilgangsmodifikatoren viktig.

    En indre klasse kan merkes med standard tilgangsmodifikatorer: public, private, protected, og package private.

    Hvorfor betyr dette noe?

    Dette påvirker hvor vi kan lage forekomster av den indre klassen i programmet vårt.

    Hvis klassen vår Seater erklært som public, kan vi lage Seatobjekter i en hvilken som helst annen klasse. Det eneste kravet er at et objekt av den ytre klassen også må eksistere.

    Forresten, vi har allerede gjort dette her:

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

    Vi fikk lett tilgang til den Handlebarindre klassen fra Mainklassen.

    Hvis vi erklærer den indre klassen som private, vil vi kunne lage objekter kun innenfor den ytre klassen.

    Vi kan ikke lenger lage et Seatobjekt "på utsiden":

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

    Du forstår sikkert logikken allerede :)

  6. Tilgangsmodifikatorer for indre klasser fungerer på samme måte som for vanlige variabler.

    Modifikatoren protectedgir tilgang til en forekomstvariabel i underklasser og klasser som er i samme pakke.

    protectedfungerer også for indre klasser. Vi kan lage protectedobjekter av den indre klassen:

    • i ytre klasse;
    • i sine underklasser;
    • i klasser som er i samme pakke.

    Hvis den indre klassen ikke har en tilgangsmodifikator ( package private), kan objekter i den indre klassen opprettes:

    • i ytre klasse;
    • i klasser som er i samme pakke.

    Du har vært kjent med modifikatorer lenge, så ingen problemer her.

Det var alt for nå :) Men ikke slapp av! Indre klasser er et ganske omfattende tema som vi vil fortsette å utforske i neste leksjon. Nå kan du friske opp minnet om kursets leksjon om indre klasser . Og neste gang, la oss snakke om statiske nestede klasser.
Kommentarer
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION