Spec-Zone .ru
спецификации, руководства, описания, API
Содержание | Предыдущий | Следующий | Индекс Спецификация языка Java
Второй Выпуск


ГЛАВА 9

Интерфейсы


Интерфейсное объявление представляет новый ссылочный тип, элементы которого являются классами, интерфейсами, константами и абстрактными методами. У этого типа нет никакой реализации, но иначе несвязанные классы могут реализовать его, обеспечивая реализации для ее абстрактных методов.

Вложенный интерфейс является любым интерфейсом, объявление которого происходит в пределах тела другого класса или интерфейса. Высокоуровневый интерфейс является интерфейсом, который не является вложенным интерфейсом.

Эта глава обсуждает общую семантику всего верхнего уровня интерфейсов (§7.6) и вложенный (§8.5, §9.5). Детали, которые являются определенными для определенных видов интерфейсов, обсуждаются в разделах, выделенных этим конструкциям.

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

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

Переменная, чья объявленный типом интерфейсный тип, может иметь как его значение ссылка на любой экземпляр класса, который реализует указанный интерфейс. Не достаточно, что класс, оказывается, реализует все абстрактные методы интерфейса; класс или один из его суперклассов, как должны фактически объявлять, реализуют интерфейс, или иначе класс, как полагают, не реализует интерфейс.

9.1 Интерфейсные Объявления

Интерфейсное объявление определяет новый именованный ссылочный тип:

Идентификатор в интерфейсном объявлении определяет имя интерфейса. Ошибка времени компиляции происходит, если у интерфейса есть то же самое простое имя как какой-либо из его классов включения или интерфейсов.

9.1.1 Интерфейсные Модификаторы

Интерфейсное объявление может включать интерфейсные модификаторы:

Общественность модификатора доступа обсуждается в §6.6. Не все модификаторы применимы ко всем видам интерфейсных объявлений. Модификаторы доступа, защищенные и частные, принадлежат только задействованным интерфейсам в пределах непосредственно объявления класса включения (§8.5) и обсуждаются в §8.5.1. Статичный модификатор доступа принадлежит только задействованным интерфейсам (§8.5, §9.5). Ошибка времени компиляции происходит, если тот же самый модификатор появляется не раз в интерфейсном объявлении.

9.1.1.1 abstract Интерфейсы

Каждый интерфейс неявно abstract. Этот модификатор является устаревшим и не должен использоваться в новых программах.

9.1.1.2 strictfp Интерфейсы

Эффект strictfp модификатор должен сделать все float или double выражения в пределах интерфейсного объявления быть явно строгим FP (§15.4).

Это подразумевает, что все вложенные типы, объявленные в интерфейсе, неявно strictfp.

9.1.2 Суперинтерфейсы и Подынтерфейсы

Если extends пункт обеспечивается, тогда объявляемый интерфейс расширяет каждый из других именованных интерфейсов и поэтому наследовал типы элемента, методы, и константы каждого из других именованных интерфейсов. Эти другие именованные интерфейсы являются прямыми суперинтерфейсами объявляемого интерфейса. Любой класс это implements объявленный интерфейс, как также полагают, реализует все интерфейсы что этот интерфейс extends.

Следующее повторяется от §4.2, чтобы сделать представление здесь более четким:

Каждый InterfaceType в extends пункт интерфейсного объявления должен назвать доступный интерфейсный тип; иначе ошибка времени компиляции происходит.

Интерфейс I непосредственно зависит от типа T, если T упоминается в extends пункт я или как суперинтерфейс или как спецификатор в пределах суперинтерфейсного имени. Интерфейс I зависит от ссылочного типа T, если какое-либо из следующих условий содержит:

Ошибка времени компиляции происходит, если интерфейс зависит от себя.

В то время как каждый класс является расширением класса Object, нет никакого единственного интерфейса, которого все интерфейсы являются расширениями.

Суперинтерфейсное отношение является переходным закрытием прямого суперинтерфейсного отношения. Интерфейсный K является суперинтерфейсом интерфейса I, если любое из следующего является истиной:

Интерфейс я, как говорят, являюсь подынтерфейсом интерфейсного K всякий раз, когда K является суперинтерфейсом меня.

9.1.3 Интерфейсные Объявления Тела и Элемента

Тело интерфейса может объявить элементы интерфейса:

Контекст объявления элемента м. объявил в или наследовался интерфейсным типом, я - все тело меня, включая любые объявления вложенного типа.

9.1.4 Доступ, чтобы Соединить интерфейсом с Именами элемента

Все интерфейсные элементы неявно public. Они доступны вне пакета, где интерфейс объявляется, если интерфейс также объявляется public или protected, в соответствии с правилами §6.6.

9.2 Интерфейсные Элементы

Элементы интерфейса:

Из этого следует, что это - ошибка времени компиляции, если интерфейс объявляет метод с той же самой подписью и различным типом возврата или несовместимый throws пункт.

Интерфейс наследовался от интерфейсов, которые он расширяет, все элементы тех интерфейсов, за исключением полей, классов, и интерфейсов, которые он скрывает и методы, которые он переопределяет.

9.3 Поле (Постоянные) Объявления

Каждое полевое объявление в теле интерфейса неявно public, static, и final. Разрешается избыточно определить любые из этих модификаторов для таких полей.

Если интерфейс объявляет поле с определенным именем, то объявление того поля, как говорят, скрывает любого и все доступные объявления полей с тем же самым именем в суперинтерфейсах интерфейса.

Это - ошибка времени компиляции для тела интерфейсного объявления, чтобы объявить два поля с тем же самым именем.

Для интерфейса возможно наследовать больше чем одно поле с тем же самым именем (§8.3.3.3). Такая ситуация сам по себе не вызывает ошибку времени компиляции. Однако, любая попытка в пределах тела интерфейса, чтобы обратиться к любому полю его простым именем приведет к ошибке времени компиляции, потому что такая ссылка неоднозначна.

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

9.3.1 Инициализация Полей в Интерфейсах

У каждого поля в теле интерфейса должно быть выражение инициализации, которое не должно быть константным выражением. Переменный инициализатор оценивается и присвоение, выполняемое точно однажды, когда интерфейс инициализируется (§12.4).

Ошибка времени компиляции происходит, если выражение инициализации для интерфейсного поля содержит ссылку простым именем к тому же самому полю или к другому полю, объявление которого происходит дословно позже в том же самом интерфейсе.

Таким образом:

interface Test {
	float f = j;
	int j = 1;
	int k = k+1;
}
причины две ошибки времени компиляции, потому что j упоминается в инициализации f прежде j объявляется и потому что инициализация k обращается к k непосредственно.

Одна тонкость здесь - то, что во время выполнения поля, которые инициализируются с постоянными величинами времени компиляции, инициализируются сначала. Это применяется также к static final поля в классах (§8.3.2.1). Это означает, в частности что у этих полей, как никогда будут наблюдать, не будет своих начальных значений по умолчанию (§4.5.5), даже окольными программами. См. §12.4.2 и §13.4.8 для большего количества обсуждения.

Если ключевое слово this (§15.8.3) или ключевое слово super (15.11.2, 15.12), происходит в выражении инициализации для поля интерфейса, затем если возникновение не в пределах тела анонимного класса (§15.9.5), ошибка времени компиляции происходит.

9.3.2 Примеры Полевых Объявлений

Следующий пример иллюстрирует некоторых (возможно тонкий) точки о полевых объявлениях.

9.3.2.1 Неоднозначные Наследованные Поля

Если два поля с тем же самым именем наследованы интерфейсом, потому что, например, два из его прямых суперинтерфейсов объявляют поля с тем именем, то единственный неоднозначный элемент заканчивается. Любое использование этого неоднозначного элемента приведет к ошибке времени компиляции. Таким образом в примере:

interface BaseColors {
	int RED = 1, GREEN = 2, BLUE = 4;
}
interface RainbowColors extends BaseColors {
	int YELLOW = 3, ORANGE = 5, INDIGO = 6, VIOLET = 7;
}
interface PrintColors extends BaseColors {
	int YELLOW = 8, CYAN = 16, MAGENTA = 32;
}
interface LotsOfColors extends RainbowColors, PrintColors {
	int FUCHSIA = 17, VERMILION = 43, CHARTREUSE = RED+90;
}
интерфейс LotsOfColors наследовал два названные поля YELLOW. Это в порядке, пока интерфейс не содержит ссылки простым именем к полю YELLOW. (Такая ссылка могла произойти в пределах переменного инициализатора для поля.)

Даже если интерфейс PrintColors должны были дать значение 3 к YELLOW вместо значения 8, ссылка на поле YELLOW в пределах интерфейса LotsOfColors все еще считался бы неоднозначным.

9.3.2.2 Умножьте Наследованные Поля

Если единственное поле наследовано многократно от того же самого интерфейса, потому что, например, и этот интерфейс и один из прямых суперинтерфейсов этого интерфейса расширяют интерфейс, который объявляет поле, то только единственный элемент заканчивается. Эта ситуация сам по себе не вызывает ошибку времени компиляции.

В примере в предыдущем разделе, полях RED, GREEN, и BLUE наследованы интерфейсом LotsOfColors больше чем одним способом, через интерфейс RainbowColors и также через интерфейс PrintColors, но ссылка на поле RED в интерфейсе LotsOfColors не считается неоднозначным потому что только одно фактическое объявление поля RED включается.

9.4 Абстрактные Объявления метода

Модификатор доступа public обсуждается в §6.6. Ошибка времени компиляции происходит, если тот же самый модификатор появляется не раз в абстрактном объявлении метода.

Каждое объявление метода в теле интерфейса неявно abstract, таким образом, его тело всегда представляется точкой с запятой, не блоком.

Каждое объявление метода в теле интерфейса неявно public.

Для совместимости с более старыми версиями платформы Java это разрешается, но обескураживается, как стиль, чтобы избыточно определить abstract модификатор для методов объявляется в интерфейсах.

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

Отметьте, что метод, объявленный в интерфейсе, не должен быть объявлен static, или ошибка времени компиляции происходит, потому что static методы не могут быть abstract.

Отметьте, что метод, объявленный в интерфейсе, не должен быть объявлен strictfp или native или synchronized, или ошибка времени компиляции происходит, потому что те ключевые слова описывают свойства реализации, а не интерфейсные свойства. Однако, метод, объявленный в интерфейсе, может быть реализован методом, который объявляется strictfp или native или synchronized в классе, который реализует интерфейс.

Это - ошибка времени компиляции для тела интерфейса, чтобы объявить, явно или неявно, два метода с той же самой подписью (имя, число параметров, и типы любых параметров) (§8.4.2). Однако, интерфейс может наследовать несколько методов с той же самой подписью (§9.4.1).

Отметьте, что метод, объявленный в интерфейсе, не должен быть объявлен final или ошибка времени компиляции происходит. Однако, метод, объявленный в интерфейсе, может быть реализован методом, который объявляется final в классе, который реализует интерфейс.

9.4.1 Наследование и Переопределение

Если интерфейс объявляет метод, то объявление того метода, как говорят, переопределяет любого и все методы с той же самой подписью в суперинтерфейсах интерфейса.

Если объявление метода в интерфейсе переопределяет объявление метода в другом интерфейсе, ошибка времени компиляции происходит, если у методов есть различные типы возврата или если у Вас есть тип возврата, и другой void. Кроме того у объявления метода не должно быть a throws пункт, который конфликтует (§8.4.4) с тем из любого метода, который это переопределяет; иначе, ошибка времени компиляции происходит.

Методы переопределяются на основе подписи подписью. Если, например, интерфейс объявляет два public методы с тем же самым именем, и подынтерфейс переопределяют одного из них, подынтерфейс все еще наследовал другой метод.

Интерфейс наследовал от его прямых суперинтерфейсов все методы суперинтерфейсов, которые не переопределяются объявлением в интерфейсе.

Для интерфейса возможно наследовать больше чем один метод с той же самой подписью (§8.4.2). Такая ситуация сам по себе не вызывает ошибку времени компиляции. Интерфейс, как полагают, наследовал все методы. Однако, ошибка времени компиляции происходит, если для каких-либо двух таких наследованных методов у или их есть различные типы возврата, или у каждого есть тип возврата, и другой void. ( throws пункты не вызывают ошибки в этом случае.) Могло бы быть несколько путей, которыми то же самое объявление метода наследовано от интерфейса. Этот факт не вызывает трудности и никогда себя результаты в ошибке времени компиляции.

9.4.2 Перегрузка

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

9.4.3 Примеры Абстрактных Объявлений метода

Следующие примеры иллюстрируют некоторых (возможно тонкий) точки об абстрактных объявлениях метода.

9.4.3.1 Пример: Переопределение

Методы, объявленные в интерфейсах, abstract и таким образом не содержите реализацию. Обо все, что может быть выполнено объявлением метода переопределения, кроме подтвердить сигнатуру метода, должно ограничить исключения, которые могли бы быть выданы реализацией метода. Вот изменение примера, показанного в §8.4.3.1:

class BufferEmpty extends Exception {
	BufferEmpty() { super(); }
	BufferEmpty(String s) { super(s); }
}
class BufferError extends Exception {
	BufferError() { super(); }
	BufferError(String s) { super(s); }
}
public interface Buffer {
	char get() throws BufferEmpty, BufferError;
}
public interface InfiniteBuffer extends Buffer {
	 char get() throws BufferError;												// override
}

9.4.3.2 Пример: Перегрузка

В примере кода:

interface PointInterface {
	void move(int dx, int dy);
}
interface RealPointInterface extends PointInterface {
	void move(float dx, float dy);
	void move(double dx, double dy);
}
имя метода move перегружается в интерфейсе RealPointInterface с тремя различными подписями, двумя из них объявленный и один наследованный. Любой не -abstract класс, который реализует интерфейс RealPointInterface должен обеспечить реализации всех трех сигнатур методов.

9.5 Объявления Типа элемента

Интерфейсы могут содержать объявления типа элемента (§8.5). Объявление типа элемента в интерфейсе неявно static и public.

Если тип элемента, объявленный с простым именем C, непосредственно включается в пределах объявления интерфейса с полностью определенным именем N, то у типа элемента есть полностью определенное имя Северная Каролина.

Если интерфейс объявляет тип элемента с определенным именем, то объявление того поля, как говорят, скрывает любого и все доступные объявления типов элемента с тем же самым именем в суперинтерфейсах интерфейса.

Интерфейс может наследовать два или больше описания типа с тем же самым именем. Ошибка времени компиляции происходит на любой попытке обратиться к любому двусмысленно наследованному классу или интерфейсу его простым именем. Если то же самое описание типа наследовано от интерфейса разнообразными путями, класс или интерфейс, как полагают, наследованы только однажды; это может быть упомянуто его простым именем без неоднозначности.


Содержание | Предыдущий | Следующий | Индекс Спецификация языка Java
Второй Выпуск
Авторское право © Sun Microsystems, Inc 2000 года. Все права защищены
Пожалуйста, отправьте любые комментарии или исправления к jls@java.sun.com