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

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

Жанры

Философия 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");

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

Любовь в академии

Алфеева Лина
1. Люба-Попаданка
Фантастика:
юмористическое фэнтези
попаданцы
сказочная фантастика
5.00
рейтинг книги
Любовь в академии

Бастард Императора. Том 3

Орлов Андрей Юрьевич
3. Бастард Императора
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Бастард Императора. Том 3

Эволюционер из трущоб. Том 8

Панарин Антон
8. Эволюционер из трущоб
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Эволюционер из трущоб. Том 8

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

INDIGO
15. Фортуна дама переменчивая
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 9. Часть 2

Кодекс Императора

Сапфир Олег
1. Кодекс Императора
Фантастика:
аниме
фэнтези
попаданцы
4.25
рейтинг книги
Кодекс Императора

Эфемер

Прокофьев Роман Юрьевич
7. Стеллар
Фантастика:
боевая фантастика
рпг
7.23
рейтинг книги
Эфемер

Черный рынок

Вайс Александр
6. Фронтир
Фантастика:
боевая фантастика
космическая фантастика
космоопера
5.00
рейтинг книги
Черный рынок

Жена по ошибке

Ардова Алиса
Любовные романы:
любовно-фантастические романы
7.71
рейтинг книги
Жена по ошибке

Эмиссар

Листратов Валерий
8. Ушедший Род
Фантастика:
боевая фантастика
аниме
попаданцы
7.50
рейтинг книги
Эмиссар

Сын ведьмы. Дилогия

Седых Александр Иванович
Сын ведьмы
Фантастика:
боевая фантастика
альтернативная история
6.15
рейтинг книги
Сын ведьмы. Дилогия

Зауряд-врач

Дроздов Анатолий Федорович
1. Зауряд-врач
Фантастика:
альтернативная история
8.64
рейтинг книги
Зауряд-врач

Кодекс Крови. Книга ХVII

Борзых М.
17. РОС: Кодекс Крови
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Кодекс Крови. Книга ХVII

Адвокат Империи 9

Карелин Сергей Витальевич
Адвокат империи
Фантастика:
городское фэнтези
аниме
дорама
фантастика: прочее
попаданцы
5.00
рейтинг книги
Адвокат Империи 9

Обрыв

Гончаров Иван Александрович
Гончаров И. А. Романы
Проза:
русская классическая проза
5.00
рейтинг книги
Обрыв