"Hi, Amigo!"

"Hi, Ellie!"

"Today we have a very interesting topic. Today I'm going to tell you about nested classes."

"If a class is declared inside another class, then it is a nested class. Non-static nested classes are called inner classes."

"Objects of an inner class are nested inside objects of the outer class and can therefore access the outer class's variables."

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

"Note that the Door class has a getDoorHeight method. It uses the Car object's height variable and returns the height of the door."

Nested classes - 1

"A Door object cannot exist independently of a Car object. After all, it uses the Car object's variables. The compiler invisibly adds to the constructor and to the Door class a reference to the outer Car object, so that methods of the inner Door class can access the outer Car class's variables and call its methods."

"Nested objects. Makes sense to me. Judging by the diagram, it's all pretty straightforward."

"And so it is. Except for a couple of nuances."

"The inner Door class has a reference to the Car object, therefore:"

1) You can't create a Door object inside a static method of the Car class, because static methods don't contain a reference to the Car object that is implicitly passed to the Door constructor.

Correct Incorrect
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) The Door class cannot contain static variables or methods.

Correct Incorrect
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;
  }
 }
}

"And what if I need a variable that is shared by all Door objects?"

"You can always simply declare it in the Car class. Then it will be shared by all Door objects nested in a Car object."

3) Note: if the inner class is declared as public, instances of it can be created outside of the outer class, but an instance of the outer class must exist first:

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

4) And one more comment that I almost forgot.

"Since we have two nested objects, the inner object's methods have access to two references called 'this':"

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

"I deliberately declared variables with the same name in the classes."

"To access a variable from the outer class when it is hidden, or to access 'this' inside an inner class, simply write 'YourClassName.this':"

How to access the 'this' of an outer (or any other) class
Car.this
Car.Door.this
Car.Door.InnerClass2.InnerClass3.this

"So, if we write 'this' inside an inner class's method, then 'this' refers to the inner class?"

"Yes. Exactly."

"What do you think of inner classes, Amigo?"

"They are very interesting. I wouldn't say they're too difficult."

"There are a lot of restrictions, but they seem quite logical after you explained where those restrictions come from and why they exist."

"Plus, I've been writing nested classes in tasks for two months, but only now do I realize what I've really been writing."

"Thanks for the great lesson, Ellie."

"I'm glad you liked it, Amigo."