— Привет, Амиго!
— Привет, Элли!
— Сегодня будет очень интересная тема. Я сегодня расскажу о внутренних классах.
Если один класс объявить внутри другого, то такой класс называется внутренним.
Объекты внутренних классов при этом вложены в объекты внешних классов и могут обращаться к переменным внешних классов.
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);
}
}
}
Обрати внимание, у класса Door(дверь) есть метод, который возвращает высоту двери – getDoorHeight, этот метод использует переменную height объекта Car.
Объект типа Door не может существовать отдельно от объекта типа Car – ведь он использует его переменные. Компилятор незаметно добавляет в конструктор и в класс Door ссылку на объект внешнего класса Car, чтобы методы внутреннего класса Door могли обращаться к переменным и вызвать методы внешнего класса Car.
— Вложенные объекты. Мне все понятно. Судя по картинке тут все элементарно.
— Так и есть. Лишь пара нюансов.
Во внутреннем классе Door имеется ссылка на объект класса Car, поэтому:
1) Нельзя создать объект Door внутри статического метода в классе Car: негде взять ссылку на объект типа Car, который неявно передается в конструктор типа Door.
Правильно | Неправильно |
---|---|
|
|
2) Класс Door не может содержать статические переменные и методы.
Правильно | Неправильно |
---|---|
|
|
— А если мне нужна общая переменная для всех объектов Door?
Ты всегда можешь объявить ее просто в классе Car – это и будет общая переменная для всех объектов Door, вложенных в объект Car.
3) Обрати внимание, что если внутренний класс объявлен как public, то его объекты можно создавать вне внешнего класса, но объект внешнего класса при этом обязан присутствовать:
Car car = new Car();
Car.Door door = car.new Door();
Car.Door door = new Car().new Door();
4) И еще одно замечание – чуть не забыла.
Т.к. у нас два вложенных объекта, то в методах внутреннего объекта доступно две ссылки 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);
}
}
}
Я специально объявила в классах одинаковые переменные.
Чтобы обратиться к переменной внешнего класса, когда она скрыта, или к this внешнего класса, достаточно написать «имя класса» точка this:
Car.this
Car.Door.this
Car.Door.InnerClass2.InnerClass3.this
— Т.е. если мы внутри метода внутреннего класса пишем this, то этот this относится к внутреннему классу?
— Да. Именно так.
Как тебе внутренние классы, Амиго?
— Очень интересно. Я бы не сказал, что очень сложно.
Есть много ограничений, но они вполне логичны, когда ты мне объяснила, откуда и зачем они берутся.
А я уже два месяца в практических заданиях постоянно пишу вложенные классы и только сейчас понял, что же я писал на самом деле.
Спасибо за отличный урок, Элли.
— Рада, что тебе понравилось, Амиго.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ