Брюс Эккель - Философия Java3
- Название:Философия Java3
- Автор:
- Жанр:
- Издательство:неизвестно
- Год:неизвестен
- ISBN:нет данных
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Брюс Эккель - Философия Java3 краткое содержание
Философия Java3 - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
//. 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). Часто такой класс называют вложенным 15(nested). Чтобы понять смысл ключевого слова static в отношении внутренних классов, следует вспомнить, что в объекте обычного внутреннего класса тайно хранится ссылка на объект создавшего его объемлющего внешнего класса. При использовании статического внутреннего класса такой ссылки не существует. Применение статического внутреннего класса означает следующее:
• для создания объекта статического внутреннего класса не нужен объект внешнего класса;
• из объекта вложенного класса нельзя обращаться к не-статическим членам внешнего класса.
Есть и еще одно различие между вложенными и обычными внутренними классами. Поля и методы обычного внутреннего класса определяются только на уровне внешнего класса, поэтому обычные внутренние классы не могут содержать статические данные, поля и классы. Но вложенные классы не имеют таких ограничений:
//• i nnerclasses/Parcel 11.java
// Вложенные (статические внутренние) классы
public class Parcel 11 {
private static class PContents implements Contents { private int i = 11; public int valueO { return i; }
}
protected static class ParcelDestination implements Destination { private String label;
private Parcel Destination(String whereTo) { label = whereTo,
}
public String readLabelO { return label; }
// Вложенные классы могут содержать другие статические элементы;
public static void f() {}
static int x = 10;
static class AnotherLevel {
public static void f() {} static int x = 10;
}
}
public static Destination destination(String s) { return new ParcelDestination(s);
}
public static Contents contO {
return new Parcel Contents О,
}
public static void main(String[] args) { Contents с = contentsO, Destination d = destinationC'TacMaHHfl"),
}
} ///;-
В методе main() не требуется объекта класса Parcelll; вместо этого для вызова методов, возвращающих ссылки на Contents и Destination, используется обычный синтаксис обращения к статическим членам класса.
Как было сказано ранее, в обычном (не-статическом) внутреннем классе для обращения к объекту внешнего класса используется специальная ссылка this. Во вложенном классе такая ссылка недействительна (по аналогии со статическими методами).
Читать дальшеИнтервал:
Закладка: