"Hej, Amigo!"

"Hej Ellie!"

"Idag har vi ett mycket intressant ämne. Idag ska jag berätta om kapslade klasser."

"Om en klass deklareras inuti en annan klass, så är det en kapslad klass. Icke-statiska kapslade klasser kallas inre klasser."

"Objekt i en inre klass är kapslade inuti objekt i den yttre klassen och kan därför komma åt den yttre klassens variabler."

Exempel
public class Car
{
 int height = 160;
 ArrayList doors = new ArrayList();

 public Car
 {
  doors.add(new Door());
  doors.add(new Door());
  doors.add(new Door());
  doors.add(new Door());
 }

class Door()
 {
  public int getDoorHeight()
  {
   return (int)(height * 0.80);
  }
 }
}

"Observera att klassen Door har en getDoorHeight-metod. Den använder Car-objektets höjdvariabel och returnerar höjden på dörren."

Kapslade klasser - 1

"Ett Door-objekt kan inte existera oberoende av ett Car-objekt. Det använder trots allt Car-objektets variabler. Kompilatorn lägger osynligt till konstruktorn och till Door-klassen en referens till det yttre Car-objektet, så att metoder för den inre Door-klassen kan komma åt den yttre Car-klassens variabler och anropa dess metoder."

"Inkapslade föremål. Det är vettigt för mig. Av diagrammet att döma är det hela ganska okomplicerat."

"Och så är det. Förutom ett par nyanser."

"Den inre dörrklassen har en referens till bilobjektet, därför:"

1) Du kan inte skapa ett Door-objekt i en statisk metod av klassen Car, eftersom statiska metoder inte innehåller en referens till Car-objektet som implicit skickas till Door-konstruktorn.

Korrekt Felaktig
public class Car
{
 public static Door createDoor()
 {
  Car car = new Car();
  return car.new Door();
 }

 public class Door
 {
  int width, height;
 }
}
public class Car
{
 public static Door createDoor()
 {
  return new Door();
 }

 public class Door
 {
  int width, height;
 }
}

2) Klassen Door kan inte innehålla statiska variabler eller metoder.

Korrekt Felaktig
public class Car
{
 public int count;
 public int getCount()
 {
  return count;
 }

 public class Door
 {
  int width, height;
 }
}
public class Car
{

 public class Door
 {
  public static int count;
  int width, height;

  public static int getCount()
  {
   return count;
  }
 }
}

"Och vad händer om jag behöver en variabel som delas av alla Door-objekt?"

"Du kan alltid helt enkelt deklarera det i Car-klassen. Sedan kommer det att delas av alla Door-objekt kapslade i ett Car-objekt."

3) Notera: om den inre klassen deklareras som offentlig kan instanser av den skapas utanför den yttre klassen, men en instans av den yttre klassen måste finnas först:

Car car = new Car();
Car.Door door = car.new Door();
Car.Door door = new Car().newDoor();

4) Och en kommentar till som jag nästan glömde.

"Eftersom vi har två kapslade objekt har det inre objektets metoder tillgång till två referenser som kallas 'detta':"

public class Car
{
 int width, height;

 public class Door
 {
  int width, height;

  public void setHeight(int height)
  {
   this.height = height;
  }

 public int getHeight()
 {
  if (height != 0)
   return this.height;
  else
   return (int)(Car.this.height * 0.8);
 }
}

"Jag deklarerade medvetet variabler med samma namn i klasserna."

"För att komma åt en variabel från den yttre klassen när den är dold, eller för att komma åt 'detta' inuti en inre klass, skriv helt enkelt 'YourClassName.this':"

Hur man kommer åt "detta" för en yttre (eller någon annan) klass
Car.this
Car.Door.this
Car.Door.InnerClass2.InnerClass3.this

"Så, om vi skriver 'detta' i en inre klasss metod, då syftar 'detta' på den inre klassen?"

"Ja exakt."

"Vad tycker du om inre klasser, Amigo?"

"De är väldigt intressanta. Jag skulle inte säga att de är för svåra."

"Det finns många restriktioner, men de verkar ganska logiska efter att du förklarat var dessa restriktioner kommer ifrån och varför de finns."

"Dessutom har jag skrivit kapslade klasser i uppgifter i två månader, men först nu inser jag vad jag egentligen har skrivit."

"Tack för den fantastiska lektionen, Ellie."

"Jag är glad att du gillade det, Amigo."