— Привіт, Аміго!
— Сьогодні буде дуже цікава тема. Я розповім про внутрішні класи.
Якщо один клас оголосити усередині іншого, то такий клас називається внутрішнім.
Об'єкти внутрішніх класів при цьому вкладені в об'єкти зовнішніх класів і можуть звертатися до змінних внутрішніх класів.
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:
Car.this
Car.Door.this
Car.Door.InnerClass2.InnerClass3.this
— Тобто якщо ми всередині методу внутрішнього класу пишемо this, цей this відноситься до внутрішнього класу?
— Так. Саме так.
Як тобі внутрішні класи, Аміго?
— Дуже цікаво. Я не сказав би, що дуже складно.
Є багато обмежень, але вони є цілком логічними після пояснення про те, звідки і навіщо вони беруться.
А я вже два місяці в практичних завданнях постійно пишу вкладені класи і тільки зараз зрозумів, що я писав насправді.
Дякую за чудовий урок.
— Добре, що тобі сподобалось, Аміго.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ