Главная » Java, Структуры данных и алгоритмы » Приведение типов внутри интерфейсов

0

В Java можно описать общие структуры данных, с помощью которых организованы элементы общего класса или интерфейса. Такие структуры могут быть использованы для хранения элементов лщбого класса, который является наследником общего класса или реализует общий интерфейс. Например, необходимо описать интерфейс Person для всех классов, связанных с людьми. Это можно сделать так, как показано во фрагменте кода 2.11.

/** Интерфейс для описания человека. 7 public interfase Person {

/** Сравнивает, совпадает ли этот человек с другим 7 public boolean equalTo (Person other);

/** Возвращает имя этого человека 7 public String getName();

!** Возвращает возраст этого человека 7

public int getAge(); }

Фрагмент кода 2.11. Интерфейс Person

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

Предположим, необходимо создать базу данных — справочник объектов класса Student, реализующий интерфейс Person и представленный во фрагменте кода 2.12. Однако объект класса Student может сравниваться лишь с другими объектами класса, так как сравнение основано на сопо-г ставлении уникальных идентификаторов студентов. Для разрешения этой проблемы необходимо преобразовать тип Person в тип Student. Это возможно еще и потому, что в справочнике находятся только объекты класса Student, то есть известно, что ссылка на любой объект типа Person является ссылкой на объект класса Student. Это соответствие позволяет исполняющей системе выполнить приведение типов в методе equalTo.

Для сравнения имен студентов выполняется явное приведение параметра other типа Person в тип Student. В данном случае присутствует подобное приведение типа, однако количество случаев, при которых возможно привести тип переменной v, обращающейся к интерфейсу U, к конкретному классу S, ограничено. В частности, данное преобразование типа разрешено, если v обращается к объекту конкретного класса Г, который наследует класс S или (Т= S), a S реализует U.

Г* Класс Ъписания студента. 7 public class Student implements Person { String id; String name; int age;

/** Конструктор. 7

public Student (String i, String n, int a) { id = i; name = n; age = a;

}

/** Количество часов учебы в неделю 7 protected int studyHours() {

return age/2 // предположительно, пропорционально возрасту

}

//** ID студента. 7 public String getID () { return id;

}

// Следующие три метода реализуют интерфейс Person. 7 public String getName() { return name;

}

public int getAge() { return age;

}

public boolean equalTo (Person other) {

Student otherStudent = (Student) other; // преобразует Person

// в Student

return (id.equals (otherStudent.getlDQ)); // сравнивает два ID.

}

}

Фрагмент кода 2.12. Класс Student, реализующий интерфейс Person

Такое родовое приведение типов позволяет создавать и общие виды структур данных, в которых указано минимальное количество требований, предъявляемых к входящим в них элементам. Во фрагменте кода 2.13 показано создание каталога пар (людей), в котором хранятся пары объектов, реализующих интерфейс Person. Метод remove выполняет поиск в содержимом каталогами удаляет определенную пару (если она существует), подобно методу fmdOther, он использует для этого метод equalTo.

/** Класс для каталога, содержащего пары объектов Person. 7 public class PersonPairDirectory {

// переменные экземпляра класса…

public PersonPairDirectory() {

// тело конструктора }

public void insert (Person person, Person other) {

// код добавления пары людей… }

public Person findOther (Person person) {

// код поиска пары, содержащей определенного человека

// (используется equalTo)

return null; // фиктивный модуль для успешного завершения компиляции // класса

}

public void remove (Person person, Person other) { // код для удаления определенной пары людей

Фрагмент кода 2.13. Класс PersonPairDirectory

Предположим, составлен каталог myDirectory, который содержит пары объектов Student — пары студентов, проживающих в одной комнате общежития. Для того чтобы найти соседа по комнате smart one указанного объекта Student, можно попытаться выполнить следующее (что на самом деле не верно):

// ЭТО НЕ ВЕРНО:

Student cute_one = myDirectory.findOther(smart_one);

В результате приведенной выше операции компилятор выдаст сообщение о необходимости явного приведения типа. Дело в том, что в данном случае производится попытка присвоить нечто типа Person некоему объекту типа Student. Для разрешения этой проблемы можно записать следующее:

// ЭТО ВЕРНО:

Student cute_one = (Student) myDirectory.findOther(smart_one);

Тип Person возвращаемого методом findOther значения преобразуется в тип Student. Данная операция возможна лишь в том случае, если известно, что метод myDirectory.fmdOther действительно возвращает объект Student. В целом интерфейсы являются удобным средством создания общих структур данных, которые могут быть впоследствии конкретизированы другими программами с помощью приведения типов.

Источник: Гудрич М.Т. Г93 Структуры данных и алгоритмы в Java / М.Т. Гудрич, Р. Тамассия; Пер. с англ. A.M. Чернухо. — Мн.: Новое знание, 2003. — 671 е.: ил.

По теме:

  • Комментарии