public void forward(int velocity) { controls forward(velocity).
}
public void leftCint velocity) { controls left(velocity).
}
public void rightOnt velocity) { controls right(velocity);
}
public void turboBoostO {
controls.turboBoostO.
}
public void up(int velocity) { controls.up(velocity):
}
public static void main(String[] args) { SpaceShipDelegation protector =
new SpaceShipDelegationC'NSEA Protector");
protector.forwarcK 100);
}
} ///:-
Как видите, вызовы методов переадресуются встроенному объекту controls, а интерфейс остается таким же, как и при наследовании. С другой стороны, делегирование позволяет лучше управлять происходящим, потому что вы можете ограничиться небольшим подмножеством методов встроенного объекта.
Хотя делегирование не поддерживается языком Java, его поддержка присутствует во многих средах разработки. Например, приведенный пример был автоматически сгенерирован в JetBrains Idea IDE.
Сочетание композиции и наследования
Композиция очень часто используется вместе с наследованием. Следующий пример демонстрирует процесс создания более сложного класса с объединением композиции и наследования, с выполнением необходимой инициализации в конструкторе:
II: reusing/PlaceSetting.java 11 Совмещение композиции и наследования, import static net.mindview.util.Print.*;
class Plate {
'PlateCint i) {
print("Конструктор Plate");
}
}
class DinnerPlate*extends Plate { DinnerPlate(int i) { super(i),
print("Конструктор DinnerPlate");
class Utensil {
Utensil(int i) {
print("Конструктор Utensil");
}
}
class Spoon extends Utensil { Spoon(int i) {
super(i);
print'CKoHCTpyKTop Spoon");
class Fork extends Utensil { Fork(int i) {
super(i);
System.out.println("Конструктор Fork");
}
class Knife extends Utensil { Knife(int i) {
super(i):
print("Конструктор Knife");
class Custom {
Custom(int i) {
print("Конструктор Custom");
public class'PIaceSetting extends Custom { private Spoon sp; private Fork frk; private Knife kn; private DinnerPlate pl; public PIaceSetting(int i) { super(i + 1); sp = new Spoon(i + 2); frk = new Fork(i + 3); kn = new Knifed + 4); pl = new DinnerPlated + 5); pri nt("Конструктор PlaceSetti ng"):
}
public static void main(String[] args) {
. PlaceSetting x = new PlaceSetting(9);
}
} /* Output: Конструктор Custom Конструктор Utensil Конструктор Spoon Конструктор Utensil Конструктор Fork Конструктор Utensil Конструктор Knife Конструктор Plate Конструктор DinnerPlate конструктор PlaceSetting *///:-
Несмотря на то, что компилятор заставляет вас инициализировать базовые классы и требует, чтобы вы делали это прямо в начале конструктора, он не следит за инициализацией встроенный объектов, поэтому вы должны сами помнить об этом.
Обеспечение правильного завершения
В Java отсутствует понятие
Во многих случаях эта модель работает, но иногда класс выполняет некоторые операции, требующие завершающих действий. Как упоминалось в главе 5, вы не знаете, когда будет вызван сборщик мусора и произойдет ли это вообще. Поэтому, если в классе должны выполняться действия по очистке, вам придется написать для этого особый метод и сделать так, чтобы программисты-клиенты знали о необходимости вызова этого метода. Более того, как описано в главе 10, вам придется предусмотреть возможные исключения и выполнить завершающие действия в секции finally.
Представим пример системы автоматизированного проектирования, которая рисует на экране изображения:
//: reusing/CADSystem.java // Обеспечение необходимого завершения package reusing:
import static net.mindview util.Print.*;
class Shape {
Shape(int i) { print("Конструктор Shape"); } void disposed { print("Завершение Shape"); }
'}
class Circle extends Shape { Circle(int i) {
super(i),
print("Рисуем окружность Circle");
}
void disposeO {
print("Стираем окружность Circle"); super. disposeO;
}
}
class Triangle extends Shape { Triangle(int i) { super(i);
print("Рисуем треугольник Triangle");
}
void disposeO {
print("Стираем треугольник Triangle"); super.disposeO;
}
}
class Line extends Shape { private int start, end; Line(int start, int end) { super(start); this.start = start; this.end = end;
print("Рисуем линию Line: " + start + ", " + end);
}
void disposeO {
print("Стираем линию Line: " + start + ", " + end). super.disposeO;
}
public class CADSystem extends Shape { private Circle c; private Triangle t; private Line[] lines = new Line[3], public CADSystem(int i) { super(i + 1).
for(int j = 0, j < lines length; j++) lines[j] = new Line(j. j*j), с = new Circled), t = new Triangle(l), print("Комбинированный конструктор").
}
void disposed {
print("CADSystem.dispose()"); // Завершение осуществляется в порядке, // обратном порядку инициализации t disposed; с.disposed;
for(int i = lines length - 1; i >=0; i--)
lines[i] .disposed; super disposed;
}
public static void main(String[] args) { CADSystem x = new CADSystem(47), try {