Студопедия

Главная страница Случайная страница

Разделы сайта

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника






Интерфейсные ссылки






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

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

Листинг 2. Интерфейсные ссылки

// Интерфейс:

interface Base{

int F(int n);

}

// Класс A реализует интерфейс Base:

class A implements Base{

// Двойной факториал числа:

public int F(int n){

if(n==1||n==2) return n;

else return n*F(n-2); }

}

// Класс B реализует интерфейс Base:

class B implements Base{

// Факториал числа:

public int F(int n){

if(n< 1) return 1;

else return n*F(n-1); }

}

class ImplDemo{

public static void main(String args[]){

// Интерфейсные переменные и создание объектов:

Base refA=new A();

Base refB=new B();

// Объектные переменные и создание объектов:

A objA=new A();

B objB=new B();

// Проверка работы методов:

System.out.println(" 1: " +refA.F(5));

System.out.println(" 2: " +refB.F(5));

System.out.println(" 3: " +objA.F(5));

System.out.println(" 4: " +objB.F(5));

// Изменение интерфейсных ссылок:

refA=objB;

refB=objA;

// Проверка результата:

System.out.println(" 5: " +refA.F(5));

System.out.println(" 6: " +refB.F(5)); }

}

В интерфейсе Base объявлен всего один метод с названием F(), целочисленным аргументом и целочисленным результатом. Классы A и B реализуют интерфейс Base, причем каждый по-своему. В классе A метод F() описан так, что им возвращается в качестве результата двойной факториал от целочисленного аргумента (напомним, что по определению двойной факториал числа n есть произведение натуральных чисел до этого числа включительно «через два», то есть n!! = n(n-2)(n-4)…). В классе B методом F() вычисляется факториал числааргумента метода (произведение натуральных чисел от 1 до числа n включительно, то есть n! =n*(n-1)*(n-2)*…*2*1). При описании метода F() в обоих классах использована рекурсия.

В главном методе программы командами Base refA=new A() и Base refB=new B() создаются два объекта классов A и B, причем ссылки на эти объекты записываются в интерфейсные переменные refA и refB. В качестве типа этих переменных указано имя интерфейса Base, а сами объекты создаются вызовом конструкторов соответствующих классов.

Затем создаются еще два объекта классов A и B, и ссылки на них записываются в объектные переменные objA и objB соответственно. Для этого используются команды A objA=new A() и B objB=new B().

После этого с помощью объектных и интерфейсных переменных несколько раз вызывается метод F() с аргументом 5. Отметим, что 5!! =15 и 5! =120. Поэтому если вызывается версия метода, описанная в классе A, результатом является число 15, а для версии метода, описанной в классе B, результат есть число 120.

В частности, при вызове метода через переменные objA и refA вызывается версия метода, описанная в классе A, а при вызове метода через переменные objB и refB — версия, описанная в классе B.

После этого командами refA=objB и refB=objA ссылки «меняются местами»: интерфейсная переменная refA ссылается на объект класса B, а интерфейсная переменная refB — на объект класса A. После этого инструкцией refA.F(5) вызывается версия метода F() из класса B, а инструкцией refB.F(5) — версия метода F(), описанная в классе A. В результате выполнения программы получаем следующее:

1: 15

2: 120

3: 15

4: 120

5: 120

6: 15

В листинге 3 приведен другой пример, в котором один класс реализует несколько интерфейсов.

Листинг 3. Реализация нескольких интерфейсов

// Первый интерфейс:

interface One{

void setOne(int n);

}

// Второй интерфейс:

interface Two{

void setTwo(int n);

}

// Суперкласс:

class ClassA{

int number;

void show(){

System.out.println(" Поле number: " +number); }

}

// Подкласс наследует суперкласс и реализует интерфейсы:

class ClassB extends ClassA implements One, Two{

int value;

// Метод первого интерфейса:

public void setOne(int n){

number=n; }

// Метод второго интерфейса:

public void setTwo(int n){

value=n; }

// Переопределение метода суперкласса:

void show(){

super.show();

System.out.println(" Поле value: " +value); }

}

class MoreImplDemo{

public static void main(String[] args){

// Интерфейсные переменные:

One ref1;

Two ref2;

// Создание объекта:

ClassB obj=new ClassB();

// Интерфейсные ссылки:

ref1=obj;

ref2=obj;

// Вызов методов:

ref1.setOne(10);

ref2.setTwo(-50);

// Проверка результата:

obj.show(); }

}

Результат выполнения этой программы имеет вид:

Поле number: 10

Поле value: -50

Кратко поясним основные этапы реализации алгоритма. Итак, имеются два интерфейса One и Two, которые реализуются классом ClassB. Кроме того, класс ClassB наследует класс ClassA. В каждом из интерфейсов объявлено по одному методу: в интерфейсе One метод setOne(), а в интерфейсе Two метод setTwo(). Оба метода не возвращают результат и имеют один целочисленный аргумент.

У суперкласса ClassA объявлено поле int number и определен метод show(), который выводит значение поля на экран. При наследовании в подклассе ClassB этот метод переопределяется так, что выводит значения двух полей: наследуемого из суперкласса поля number и поля int value, описанного непосредственно в подклассе.

В классе ClassB методы setOne() и setTwo() реализованы так, что первый метод присваивает значение полю number, второй — полю value.

В главном методе программы создаются две интерфейсные переменные: переменная ref1 типа One и переменная ref2 типа Two. Кроме того, создается объект obj класса ClassB. В качестве значений интерфейсным переменным присваиваются ссылки на объект obj. Это возможно, поскольку класс ClassB реализует интерфейсы One и Two. Однако в силу того же обстоятельства через переменную ref1 можно получить доступ только к методу setOne(), а через переменную

ref2 — только к методу setTwo(). Командами ref1.setOne(10) и ref2.setTwo(-50)

полям объекта obj присваиваются значения, а командой obj.show() значения полей выводятся на экран.

 






© 2023 :: MyLektsii.ru :: Мои Лекции
Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав.
Копирование текстов разрешено только с указанием индексируемой ссылки на источник.