Чтение онлайн

на главную - закладки

Жанры

Философия Java3

Эккель Брюс

Шрифт:

Невозможно создать объект внутреннего класса, не имея ссылки на внешний класс. Но если создать вложенный класс (статический внутренний класс), ссылка на объект внешнего класса не нужна.

Рассмотрим пример использования .new в примере Parcel:

// innerclasses/Parcel3 java

// Использование new для создания экземпляров внутренних классов

public class Parcel3 { class Contents {

private int i = 11,

public int valueO { return i; }

}

class Destination {

private String label;

DestinationCString whereTo) { label = whereTo; } String readLabelO { return label; }

}

public static void main(String[] args) { Parcel3 p = new Parcel3; II

Для создания экземпляра внутреннего класса // необходимо использовать экземпляр внешнего класса: Pa reel 3. Contents с = p. new ContentsO; Parcel3.Destination d = p new Destination"Танзания");

}

} III -

Внутренние классы и восходящее преобразование

Мощь внутренних классов по-настоящему проявляется при выполнении восходящего преобразования к базовому классу, и в особенности к интерфейсу. (Получение ссылки на интерфейс по ссылке на реализующий его объект ничем принципиально не отличается от восходящего преобразования к базовому классу.) Причина в том, что внутренний класс — реализация интерфейса — может быть абсолютно невидимым и недоступным окружающему миру, а это очень удобно для сокрытия реализации. Все, что вы при этом получаете, — ссылку на базовый класс или интерфейс.

Для начала определим интерфейсы для предыдущих примеров:

// i nnerclasses/Desti nati on.java public interface Destination {

String readLabel; } Hill-. innerclasses/Contents.java public interface Contents {

int valueO; } ///-

Теперь интерфейсы Contents и Destination доступны программисту-клиенту. (Помните, что в объявлении interface все члены класса автоматически являются открытыми (public).)

При получении из метода ссылки на базовый класс или интерфейс возможны ситуации, в которых вам не удастся определить ее точный тип, как здесь:

//. innerclasses/TestParcel.java

class Parcel4 {

private class PContents implements Contents { private int i = 11; public int valueO { return i; }

}

protected class PDestination implements Destination { private String label; private PDestination(String whereTo) { label = whereTo;

}

public String readLabelО { return label; }

}

public Destination destination(String s) { return new PDestination(s);

}

public Contents contents О {

return new PContentsО;

public class TestParcel {

public static void main(String[] args) { Parcel4 p = new Parcel4; Contents с = p.contents О; Destination d = p.destinationC'TacMaHMfl"); // Запрещено - нет доступа к private-классу: //! Parcel4.PContents pc = p.new PContentsО;

}

} ///-

В класс Parcel4 было добавлено кое-что новое: внутренний класс PContents является закрытым (private), поэтому он недоступен для всех, кроме внешнего класса Рагсе14. Класс PDestination

объявлен как protected, следовательно, доступ к нему имеют только класс Parcel4, классы из одного пакета с Рагсе14 (так как спецификатор protected также дает доступ з пределах пакета) и наследники класса Рагсе14. Таким образом, программист-клиент обладает ограниченной информацией и доступом к этим членам класса. Более того, нельзя даже выполнить нисходящее преобразование к закрытому (private) внутреннему классу (или protected, кроме наследников), поскольку его имя недоступно, как показано в классе Test. Таким образом, закрытый внутренний класс позволяет разработчику класса полностью запретить использование определенных типов и скрыть все детали реализации класса. Вдобавок, расширение интерфейса с точки зрения программиста-клиента не будет иметь смысла, поскольку он не сможет получить доступ к дополнительным методам, не принадлежащим к открытой части класса. Наконец, у компилятора Java появится возможность оптимизировать код.

Внутренние классы в методах и областях действия

Ранее мы рассмотрели ряд типичных применений внутренних классов. В основном ваш код будет содержать «простые» внутренние классы, смысл которых понять нетрудно. Однако синтаксис внутренних классов скрывает множество других, не столь тривиальных способов их использования: внутренние классы можно создавать внутри метода или даже в пределах произвольного блока. На то есть две причины:

• как было показано ранее, вы реализуете некоторый интерфейс, чтобы затем создавать и возвращать ссылку его типа;

• вы создаете вспомогательный класс для решения сложной задачи, но при этом не хотите, чтобы этот класс был открыт для посторонних.

В следующих примерах рассмотренная недавно программа будет изменена, благодаря чему у нас появятся:

• класс, определенный внутри метода;

• класс, определенный внутри области действия (блока), которая находится внутри метода;

• безымянный класс, реализующий интерфейс;

• безымянный класс, расширяющий класс, у которого отсутствует конструктор по умолчанию;

• безымянный класс, выполняющий инициализацию полей;

• безымянный класс, осуществляющий конструирование посредством инициализации экземпляра (безымянные внутренние классы не могут иметь конструкторы).

Первый пример демонстрирует создание целого класса в контексте метода (вместо создания в контексте другого класса). Такие внутренние классы называются локальными:

//• innerclasses/Parce!5.java

// Вложение класса в тело метода.

public class Parcel5 {

public Destination dest(String s) {

class PDestination implements Destination { private String label; private PDestination(String whereTo) { label = whereTo;

}

public String readLabelO { return label; } _ Л

продолжение &

}

return new PDestination(s).

}

public static void main(String[] args) { Parcel5 p = new Parcel50; Destination d = p destinationC'TacMaHHH");

Поделиться:
Популярные книги

Офицер-разведки

Поселягин Владимир Геннадьевич
2. Красноармеец
Фантастика:
боевая фантастика
попаданцы
5.00
рейтинг книги
Офицер-разведки

Кадры решают все

Злотников Роман Валерьевич
2. Элита элит
Фантастика:
боевая фантастика
попаданцы
альтернативная история
8.09
рейтинг книги
Кадры решают все

Кодекс Охотника. Книга XII

Винокуров Юрий
12. Кодекс Охотника
Фантастика:
боевая фантастика
городское фэнтези
аниме
7.50
рейтинг книги
Кодекс Охотника. Книга XII

Город Богов

Парсиев Дмитрий
1. Профсоюз водителей грузовых драконов
Фантастика:
юмористическая фантастика
детективная фантастика
попаданцы
5.00
рейтинг книги
Город Богов

Соль этого лета

Рам Янка
1. Самбисты
Любовные романы:
современные любовные романы
6.00
рейтинг книги
Соль этого лета

На границе империй. Том 10. Часть 1

INDIGO
Вселенная EVE Online
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 10. Часть 1

Новые горизонты

Лисина Александра
5. Гибрид
Фантастика:
попаданцы
технофэнтези
аниме
сказочная фантастика
фэнтези
5.00
рейтинг книги
Новые горизонты

Черный маг императора

Герда Александр
1. Черный маг императора
Фантастика:
юмористическая фантастика
попаданцы
аниме
5.00
рейтинг книги
Черный маг императора

Убивать чтобы жить 5

Бор Жорж
5. УЧЖ
Фантастика:
боевая фантастика
космическая фантастика
рпг
5.00
рейтинг книги
Убивать чтобы жить 5

Ополченец

Криптонов Василий Анатольевич
1. Мир падающих звезд
Фантастика:
фэнтези
попаданцы
альтернативная история
5.00
рейтинг книги
Ополченец

Маленькая хозяйка большого герцогства

Вера Виктория
2. Герцогиня
Любовные романы:
любовно-фантастические романы
7.80
рейтинг книги
Маленькая хозяйка большого герцогства

Кровь и Пламя

Михайлов Дем Алексеевич
7. Изгой
Фантастика:
фэнтези
8.95
рейтинг книги
Кровь и Пламя

Черный маг императора 3

Герда Александр
3. Черный маг императора
Фантастика:
попаданцы
аниме
5.00
рейтинг книги
Черный маг императора 3

Восемь бусин на тонкой ниточке

Михалкова Елена Ивановна
Настоящий детектив
Детективы:
прочие детективы
9.30
рейтинг книги
Восемь бусин на тонкой ниточке