CodeGym/Java blog/Tilfældig/Indlejrede indre klasser
John Squirrels
Niveau
San Francisco

Indlejrede indre klasser

Udgivet i gruppen
Hej! I dag vil vi tage et vigtigt emne op - hvordan indlejrede klasser fungerer i Java. Java lader dig oprette klasser i en anden klasse:
class OuterClass {
    ...
    static class StaticNestedClass {
        ...
    }
    class InnerClass {
        ...
    }
}
Disse interne klasser kaldes indlejrede. De er opdelt i 2 typer:
  1. Ikke-statiske indlejrede klasser. Disse kaldes også indre klasser.
  2. Statiske indlejrede klasser.
Til gengæld har indre klasser to adskilte underkategorier. Ud over at en indre klasse blot er en indre klasse, kan det også være:
  • en lokal klasse
  • en anonym klasse
Forvirret? :) Det er okay. Her er et diagram for klarhedens skyld. Vend tilbage til det i løbet af lektionen, hvis du pludselig bliver forvirret! Indlejrede indre klasser - 2I dagens lektion vil vi diskutere indre klasser (også kendt som ikke-statiske indlejrede klasser). De er specielt fremhævet i det overordnede diagram, så du ikke farer vild :) Lad os starte med det åbenlyse spørgsmål: hvorfor kaldes de "indre" klasser? Svaret er ganske enkelt: fordi de er skabt inde 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 felter og 1 metode: start(). Indlejrede indre klasser - 3Den adskiller sig fra en almindelig klasse ved, at den indeholder to klasser: Handlebarog Seat. Deres kode er skrevet inde i Bicycleklassen. Disse er fuldgyldige klasser: Som du kan se, har hver af dem sine egne metoder. På dette tidspunkt har du måske et spørgsmål: hvorfor i alverden skulle vi sætte en klasse ind i en anden? Hvorfor gøre dem til indre klasser? Tja, antag, at vi har brug for separate klasser til begreberne styr og sæde i vores program. Det er selvfølgelig ikke nødvendigt for os at gøre dem indlejrede! Vi kan lave almindelige klasser. For eksempel sådan her:
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!");
   }
}
Meget godt spørgsmål! Selvfølgelig er vi ikke begrænset af teknologien. At gøre det er bestemt en mulighed. Her er det vigtige mere det korrekte design af klasserne ud fra et specifikt programs perspektiv og dets formål. Indre klasser er til at adskille en enhed, der er uløseligt forbundet med en anden entitet. Styr, sæder og pedaler er en del af en cykel. Adskilt fra cyklen giver de ikke meget mening. Hvis vi lavede alle disse koncepter adskilte offentlige klasser, ville vi have haft koden som denne i vores program:
public class Main {

   public static void main(String[] args) {
       Handlebar handlebar = new Handlebar();
       handlebar.right();
   }
}
Hmm... Betydningen af ​​denne kode er endda svær at forklare. Vi har et eller andet uklart styr (hvorfor er det nødvendigt? Ingen idé, for at være ærlig). Og dette håndtag drejer til højre... helt af sig selv, uden en cykel... af en eller anden grund. Ved at adskille konceptet med styret fra konceptet med cyklen, mistede vi noget logik i vores program. Ved at bruge en indre klasse ser koden meget anderledes ud:
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();
   }
}
Konsoludgang:
Seat up!
Let's go!
Steer left!
Steer right!
Nu giver det vi ser pludselig mening! :) Vi lavede et cykelobjekt. Vi skabte to cykel "underobjekter" - et styr og et sæde. Vi hævede sædet for komfort, og vi gik i gang: træde i pedalerne og styre efter behov! :) De metoder, vi har brug for, kaldes på de relevante objekter. Det hele er enkelt og bekvemt. I dette eksempel forbedrer adskillelse af styr og sæde indkapslingen (vi skjuler data om cykeldelene i den relevante klasse) og lader os skabe en mere detaljeret abstraktion. Lad os nu se på en anden situation. Antag, at vi vil lave et program, der simulerer en cykelbutik og reservedele til cykler. Indlejrede indre klasser - 4I denne situation vil vores tidligere løsning ikke fungere. I en cykelbutik giver hver enkelt cykeldel mening, selv når den er adskilt fra en cykel. For eksempel får vi brug for metoder som "sælg pedaler til en kunde", "køb et nyt sæde" osv. Det ville være en fejl at bruge indre klasser her - hver enkelt cykeldel i vores nye program har betydning, der står på sin egen: den kan adskilles fra begrebet en cykel. Det er præcis, hvad du skal være opmærksom på, hvis du spekulerer på, om du skal bruge indre klasser eller organisere alle entiteterne som separate klasser. Objektorienteret programmering er god, fordi den gør det nemt at modellere virkelige enheder. Dette kan være dit vejledende princip, når du beslutter dig for, om du vil bruge indre klasser. I en rigtig butik, reservedele er adskilt fra cykler - det er okay. Det betyder, at det også er i orden, når man designer et program. Okay, vi har fundet ud af "filosofien" :) Lad os nu stifte bekendtskab med vigtige "tekniske" træk ved indre klasser. Her er hvad du helt sikkert skal huske og forstå:
  1. Et objekt af en indre klasse kan ikke eksistere uden et objekt af en ydre klasse.

    Dette giver mening: det er derfor, vi lavede Seatog Handlebarindre klasser i vores program - så vi ikke ender med forældreløse styr og sæder.

    Denne kode kompilerer ikke:

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

    En anden vigtig egenskab følger heraf:

  2. Et objekt i en indre klasse har adgang til variablerne i den ydre klasse.

    Lad os f.eks. tilføje en int seatPostDiametervariabel (der repræsenterer sadelpindens diameter) til vores Bicycleklasse.

    Så i den Seatindre klasse kan vi lave en displaySeatProperties()metode, der viser sædeegenskaberne:

    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 nu kan vi vise disse oplysninger i vores program:

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

    Konsoludgang:

    Seat properties: seatpost diameter = 40

    Bemærk:den nye variabel erklæres med den mest strenge adgangsmodifikator ( private). Og stadig har den indre klasse adgang!

  3. Et objekt af en indre klasse kan ikke oprettes i en statisk metode af en ydre klasse.

    Dette forklares af de specifikke træk ved, hvordan indre klasser er organiseret. En indre klasse kan have konstruktører med parametre eller bare standardkonstruktøren. Men uanset, når vi skaber et objekt af en indre klasse, overføres en reference til objektet for den ydre klasse usynligt til det skabte objekt af den indre klasse. Tilstedeværelsen af ​​en sådan objektreference er trods alt et absolut krav. Ellers vil vi ikke være i stand til at skabe objekter af den indre klasse.

    Men hvis en metode for den ydre klasse er statisk, så har vi måske ikke et objekt af den ydre klasse! Og dette ville være en krænkelse af logikken i, hvordan en indre klasse fungerer. I denne situation vil compileren generere en fejl:

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

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

    Men uden et objekt fra den ydre klasse, vil vi ikke have adgang til den indre klasse.

    En klar modsigelse! Dette er grunden til, at statiske variable og metoder ikke er tilladt i indre klasser.

    Compileren vil generere en fejl, hvis du prøver at oprette 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 opretter et objekt af en indre klasse, er dets adgangsmodifikator vigtig.

    En indre klasse kan markeres med standardadgangsmodifikatorerne: public, private, protected, og package private.

    Hvorfor betyder det noget?

    Dette påvirker, hvor vi kan skabe forekomster af den indre klasse i vores program.

    Hvis vores Seatklasse er erklæret som public, kan vi oprette Seatobjekter i enhver anden klasse. Det eneste krav er, at et objekt af den ydre klasse også skal eksistere.

    Det har vi forresten allerede gjort 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 fik nemt adgang til den Handlebarindre klasse fra Mainklassen.

    Hvis vi erklærer den indre klasse som private, vil vi kun være i stand til at oprette objekter inden for den ydre klasse.

    Vi kan ikke længere skabe et Seatobjekt "på ydersiden":

    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 allerede logikken :)

  6. Adgangsmodifikatorer for indre klasser fungerer på samme måde som for almindelige variable.

    Modifikatoren protectedgiver adgang til en instansvariabel i underklasser og klasser, der er i den samme pakke.

    protectedfungerer også for indre klasser. Vi kan skabe protectedobjekter af den indre klasse:

    • i den ydre klasse;
    • i dets underklasser;
    • i klasser, der er i samme pakke.

    Hvis den indre klasse ikke har en adgangsmodifikator ( package private), kan objekter af den indre klasse oprettes:

    • i den ydre klasse;
    • i klasser, der er i samme pakke.

    Du har været fortrolig med modifikatorer i lang tid, så ingen problemer her.

Det var alt for nu :) Men slap ikke af! Indre klasser er et ret omfattende emne, som vi fortsætter med at udforske i den næste lektion. Nu kan du genopfriske din hukommelse om vores kursuss lektion om indre klasser . Og næste gang, lad os tale om statiske indlejrede klasser.
Kommentarer
  • Populær
  • Ny
  • Gammel
Du skal være logget ind for at skrive en kommentar
Denne side har ingen kommentarer endnu