русс | укр

Языки программирования

ПаскальСиАссемблерJavaMatlabPhpHtmlJavaScriptCSSC#DelphiТурбо Пролог

Компьютерные сетиСистемное программное обеспечениеИнформационные технологииПрограммирование

Все о программировании


Linux Unix Алгоритмические языки Аналоговые и гибридные вычислительные устройства Архитектура микроконтроллеров Введение в разработку распределенных информационных систем Введение в численные методы Дискретная математика Информационное обслуживание пользователей Информация и моделирование в управлении производством Компьютерная графика Математическое и компьютерное моделирование Моделирование Нейрокомпьютеры Проектирование программ диагностики компьютерных систем и сетей Проектирование системных программ Системы счисления Теория статистики Теория оптимизации Уроки AutoCAD 3D Уроки базы данных Access Уроки Orcad Цифровые автоматы Шпаргалки по компьютеру Шпаргалки по программированию Экспертные системы Элементы теории информации

Безымянные внутренние классы


Дата добавления: 2015-06-12; просмотров: 1088; Нарушение авторских прав


Следующий пример выглядит немного странно:

//: innerclasses/Parcel7.java

// Метод возвращает экземпляр безымянного внутреннего класса

public class Parcel7 {

public Contents contents() {

return new Contents() {// Вставить определение класса

private int i = 11;

public int value() { return i; }

}; // В данной ситуации точка с запятой необходима

}

public static void main(String[] args) {

Parcel7 p = new Parcel7();

Contents c = p.contents();

}

}

Метод contents() совмещает создание возвращаемого значения с определением класса, который это возвращаемое значение и представляет! Вдобавок, этот класс является безымянным — у него отсутствует имя. Ситуация запутывается еще тем, что поначалу мы будто бы приступаем к созданию объекта Contents, а потом, остановившись перед точкой с запятой, говорим: «Стоп, а сюда я подкину определение класса».

Такая необычная форма записи значит буквально следующее: «Создать объект безымянного класса, который унаследован от Contents». Ссылка, которая возвращается при этом из выражения new, автоматически повышается до базового типа Contents. Синтаксис записи безымянного внутреннего класса является укороченной формой записи такой конструкции:

//: innerclasses/Parcel7b.java

// Расширенная версия Parcel7.java

public class Parcel7b {

class MyContents implements Contents {

private int i = 11;

public int value() { return i; }

}

public Contents contents() { return new MyContents(); }

public static void main(String[] args) {

Parcel7b p = new Parcel7b();

Contents c = p.contents();

}

}

В безымянном внутреннем классе базовый класс Contents создается с использованием конструктора по умолчанию. Следующая программа показывает, как следует поступать, если базовый класс требует вызова конструктора с аргументами:



//: innerclasses/Parcel8.java

// Вызов конструктора базового класса.

public class Parcel8 {

public Wrapping wrapping(int x) {

// Вызов конструктора базового класса:

return new Wrapping(x) { // // аргумент конструктора.

public int value() {

return super.value() * 47;

}

}; // // Требуется точка с запятой

}

public static void main(String[] args) {

Parcel8 p = new Parcel8();

Wrapping w = p.wrapping(10);

}

}

Требуемый аргумент просто передается в конструктор базового класса, как в рассмотренном примере х в выражении new Wrapping(x). Хотя это обычный класс с реализацией, Wrapping также используется в качестве общего «интерфейса» для своих производных классов:

//: innerclasses/Wrapping.java

public class Wrapping {

private int i;

public Wrapping(int x) { i = x; }

public int value() { return i; }

}

Класс Wrapping имеет конструктор с аргументом — просто для того, чтобы ситуация стала чуть более интересной. Точка с запятой в конце безымянного внутреннего класса поставлена вовсе не для того, чтобы обозначить конец тела класса (как делается в C++). Вместо этого она указывает на конец выражения, в котором содержится внутренний класс. Таким образом, в данном случае ее использование ничем не отличается от обычного. Инициализацию также можно провести в точке определения полей безымянного класса:

//: innerclasses/Parcel9.java

// Безымянный внутренний класс, выполняющий инициализацию.

// Более короткая версия программы Parcel5.java

 

public class Parcel9 {

// Для использования в безымянном внутреннем классе

// аргументы должны быть неизменны (final)

public Destination destination(final String dest) {

return new Destination() {

private String label = dest;

public String readLabel() { return label; }

};

}

public static void main(String[] args) {

Parcel9 p = new Parcel9();

Destination d = p.destination("Tasmania");

}

}

Если вы определяете безымянный внутренний класс и хотите при этом использовать объекты, определенные вне этого внутреннего класса, компилятор требует, чтобы переданные на них ссылки объявлялись неизменными (final), как это сделано аргументе destination(). Без такого объявления вы получите сообщение об ошибке при компиляции программы.

Пока мы ограничиваемся простым присваиванием значений полям, указанный подход работает. А если понадобится выполнить некоторые действия, свойственные конструкторам? В безымянном классе именованный конструктор определить нельзя (раз у самого класса нет имени!), но инициализация экземпляра (instance initialization) фактически позволяет добиться желаемого эффекта:

//: innerclasses/AnonymousConstructor.java

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

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

 

abstract class Base {

public Base(int i) {

print("Base constructor, i = " + i);

}

public abstract void f();

}

 

public class AnonymousConstructor {

public static Base getBase(int i) {

return new Base(i) {

{ print("Inside instance initializer"); }

public void f() {

print("In anonymous f()");

}

};

}

public static void main(String[] args) {

Base base = getBase(47);

base.f();

}

}

<spoiler text="Output:">

Base constructor, i = 47

Inside instance initializer

In anonymous f()

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

//: innerclasses/Parcel10.java

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

// конструирования безымянного внутреннего класса

public class Parcel10 {



<== предыдущая лекция | следующая лекция ==>
Внутренние классы в методах и областях действия | Снова о методе-фабрике


Карта сайта Карта сайта укр


Уроки php mysql Программирование

Онлайн система счисления Калькулятор онлайн обычный Инженерный калькулятор онлайн Замена русских букв на английские для вебмастеров Замена русских букв на английские

Аппаратное и программное обеспечение Графика и компьютерная сфера Интегрированная геоинформационная система Интернет Компьютер Комплектующие компьютера Лекции Методы и средства измерений неэлектрических величин Обслуживание компьютерных и периферийных устройств Операционные системы Параллельное программирование Проектирование электронных средств Периферийные устройства Полезные ресурсы для программистов Программы для программистов Статьи для программистов Cтруктура и организация данных


 


Не нашли то, что искали? Google вам в помощь!

 
 

© life-prog.ru При использовании материалов прямая ссылка на сайт обязательна.

Генерация страницы за: 2.153 сек.