78

78


//. innerclasses/AnonymousConstructor.java

II Создание конструктора для безымянного внутреннего класса.

import static net.mindview.util.Print.*,

abstract class Base {

public Base(int i) {

print("Конструктор Base, i = " + i);

}

public abstract public void f();

}

public class AnonymousConstructor {

public static Base getBase(int i) { return new Base(i) {

{ рпгйС'Инициализация экземпляра"); } public void f() {

print ("Безымянный fO").

}

}.

}

public static void main(String[] args) { Base base = getBase(47); base.fO;

}).

}

} /* Output.

Конструктор Base, i = 47

Инициализация экземпляра

Безымянный f()

*///.-

В таком случае переменная iне обязанабыть неизменной (final). И хотя i пе­редается базовому конструктору безымянного класса, она никогда не использу­ется напрямуювнутрибезымянного класса.

Вернемся к нашим объектам Parcel, на этот раз выполнив для них инициа­лизацию экземпляра. Отметьте, что параметры метода destination() должны быть объявлены неизменными, так как они используются внутри безымянно­го класса:

II- innerclasses/ParcellO.java

II Демонстрация "инициализации экземпляра" для

IIконструирования безымянного внутреннего класса.продолжение &

public class Parcel 10 { public Destination

destination(final String dest, final float price) { return new Destination() { private int cost,

// Инициализация экземпляра для каждого объекта. {

cost = Math round(price), if(cost > 100)

System out println("Превышение бюджета!"),

}

private String label = dest,

public String readLabelO { return label, }

}.

}

public static void main(String[] args) {

Parcel 10 p = new Parcel 100.

Destination d = p destination"Тасмания". 101 395F),

}

} /* Output- Превышение бюджета! */// -

Внутри инициализатора экземпляра виден код, недоступный при инициали­зации полей (то есть команда if). Поэтому инициализатор экземпляра фактиче­ски является конструктором безымянного внутреннего класса. Конечно, воз­можности его ограничены; перегружать такой инициализатор нельзя, и поэтому он будет присутствовать в классе только в единственном числе.

Возможности безымянных внутренних классов несколько ограничены по сравнению с обычным наследованием — они могут либо расширять класс, либо реализовывать интерфейс, но не то и другое одновременно. А если вы вы­берете второй вариант, реализовать можно только один интерфейс.

Снова о методе-фабрике

Посмотрите, насколько приятнее выглядит пример interfaces/Factories.java при использовании безымянных внутренних классов:

// innerclasses/Factories java import static net.mindview util Print *;

interface Service { void methodic), void method2(),

}

interface SemceFactory { Service getServiceO;

}

class Implementationl implements Service { private ImplementationlO {}

public void methodic) {printC"Implementationl methodl");} public void method2() {print("Implementationl method2");}

public static ServiceFactory factory = new ServiceFactoryO {

public Service getServiceO {

return new ImplementationlO;

class Implementation2 implements Service { private Implementation20 {}

public void methodlO {print("Implementation2 methodl"),) public void method2() {print("Implementation2 method2"),j public static ServiceFactory factory = new ServiceFactoryO {

public Service getServiceO {

return new Implementation2();

public class Factories {

public static void serviceConsumer(ServiceFactory fact) { Service s = fact.getServiceO; s methodlO; s method2();

}

public static void main(String[] args) {

serviceConsumer(Implementationl.factory); // Реализации полностью взаимозаменяемы: servi ceConsumer(Implementati on2.factory);

}

} /* Output- Implementationl methodl Implementationl method2 Implementation2 methodl Implementation2 method2 */// ~

Теперь конструкторы Implementationl и Implementation2 могут быть закрытыми, и фабрику необязательно оформлять в виде именованного класса. Кроме того, часто бывает достаточно одного фабричного объекта, поэтому в данном случае он создается как статическое поле в реализации Service. Наконец, итоговый син­таксис выглядит более осмысленно.

Пример interfaces/Games.java тоже можно усовершенствовать с помощью бе­зымянных внутренних классов:

//. innerclasses/Games.java

// Использование анонимных внутренних классов в библиотеке Game import static net.mindview.util.Print.*;

interface Game { boolean moveO; } interface GameFactory { Game getGameO; }

class Checkers implements Game { private Checkers О {} private int moves = 0;

private static final int MOVES = 3;продолжение &

class Chess implements Game { private ChessO {} private int moves = 0; private static final int MOVES = 4; public boolean moveO {

print("Chess move " + moves); return ++moves != MOVES;

}

public static GameFactory factory = new GameFactoryO { public Game getGameO { return new ChessO; }

}:

}

public class Games {

public static void piayGame(GameFactory factory) { Game s = factory.getGameO; while(s. moveO)

}

public static void main(String[] args) { pi ayGame(Checkers.factory); piayGame(Chess.factory);

}

} /* Output: Checkers move 0 Checkers move 1 Checkers move 2 Chess move 0 Chess move 1 Chess move 2 Chess move 3 *///•-

Вспомните совет, данный в конце предыдущей главы:отдавать предпочте­ние классам перед интерфейсами.Если архитектура системы требует примене­ния интерфейса, вы это поймете. В остальных случаях не применяйте интер­фейсы без крайней необходимости.

public boolean moveО {

print("Checkers move " + moves); return ++moves != MOVES;

}

public static GameFactory factory = new GameFactoryO { public Game getGameO { return new Checkers О; }

Вложенные классы

Если связь между объектом внутреннего класса и объектом внешнего класса не нужна, можно сделать внутренний класс статическим (объявить его как static). Часто такой класс называютвложенным[2]
(nested). Чтобы понять смысл ключевого

слова static в отношении внутренних классов, следует вспомнить, что в объекте обычного внутреннего класса тайно хранится ссылка на объект создавшего его объемлющего внешнего класса. При использовании статического внутреннего класса такой ссылки не существует. Применение статического внутреннего класса означает следующее: