<<
>>

Родовые классы в языке Java

В языке Java у родовых АТД в качестве родовых параметров должны быть классы. До появления в этом языке механизма родовых параметров роль обобщенных типов выполняли коллекции из библиотеки классов, такие как LinkedList и ArrayList.
Все типы коллекций сохранялись в экземплярах класса Object, поэтому они могли содержать любые объекты (кроме примитивных объектов). Такие типы коллекций были способны нести в себе несколько типов (таких, которые являются классами). В связи с этим надо констатировать следующее:

? Любое извлечение объекта из коллекции должно сопровождаться явным приведением объекта к соответствующему типу.

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

? Любые коллекции не могут содержать величины примитивных типов. Перед сохранением в ArrayList целую величину нужно положить в экземпляр класса Integer.

Например, рассмотрим следующий фрагмент:

//* Создать объект класса ArrayList ArrayList theArray = new ArrayList();

//* Создать элемент theArray.add(0, new Integer(72));

//* Получить первый объект

Integer theInt = (Integer) theArray.get(0);

В настоящее время классы коллекций, среди которых наиболее популярным считают ArrayList, могут стать родовыми классами.

Такие классы конкретизируются вызовом конструктора new и передачей ему родового параметра, заключенного в угловые скобки. К примеру, класс ArrayList можно конкретизировать для сохранения объектов класса Integer и получить конкретный объект:

ArrayList theArray = new ArrayList ();

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

Язык Java также включает интерфейсы для таких коллекций, как списки, очереди и множества.

Пользователи могут определять свои собственные родовые классы. Например, мы можем записать: public class TheClass {

}

Данный класс можно конкретизировать и создать соответствующий объект следующим образом:

TheClass theString;

У подобных пользовательских родовых классов есть определенные недостатки:

? они не могут хранить примитивные величины;

? элементы не могут индексироваться. Элементы должны добавляться к коллекциям методом add.

Параметрический полиморфизм в АТД

421

Давайте реализуем родовой стек на основе коллекции ArrayList: import java.util.*; public class NewStack {

private ArrayList refStack;

private int maxLen;

public NewStack() { // A constructor refStack = new ArrayList (); maxLen = 499;

}

public void push(T newValue) {

if (refStack.size() == maxLen)

System.out.println(''Error in push-stack is full");

else

refStack.add(newValue);

}

public void pop() {

if (refStack.isEmpty());

System.out.println(''Error in pop-stack is empty");

else

refStack.remove(refStack.size() - 1);

}

public T top() {

return (refStack.get(refStack.size() - 1));

}

public boolean empty() {return (refStack.isEmpty());

}

Здесь последний элемент в ArrayList находится с помощью метода size, который возвращает количество элементов в структуре. Элементы удаляются из структуры при помощи метода remove.

Рассматриваемый класс может быть конкретизирован для типа String (с построением соответствующего объекта) следующим образом:

NewStack theStack = new NewStack ();

Как упоминалось в главе 13, в языке поддерживаются подстановочные классы. Например, Collection является подстановочным классом для всех классов коллекций. Это позволяет написать метод, который в качестве типа параметра может использовать любой тип коллекции.

Поскольку коллекция сама по себе является родовой, класс Collection можно считать родовым для родового класса.

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

Collection strColln = new ArrayList();

Фактически, здесь запрещается добавление в коллекцию объектов, не имеющих типа String.

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

422

Глава 15. Абстрактные типы данных

класса типом, не поддерживающим метод compareTo, нужно задать следующий родовой параметр:

В языке Java Comparable является интерфейсом, в котором объявлен метод compareTo. Если в определении класса будет записан этот родовой тип, то вводится запрет на конкретизацию любым типом, не реализующим Comparable. Использование зарезервированного слова extends в данном контексте выглядит, по меньшей мере, странно, очевидно разработчики намекали на ассоциацию с понятием подтипа.

<< | >>

Еще по теме Родовые классы в языке Java:

  1. О языке и методе
  2. Приложение к § 12 О родовых и благоприобретенных имениях
  3. Родовой сценарий
  4. Родовой сценарий
  5. Установки — на естественном языке внутренней речи.
  6. Установки — на естественном языке внутренней речи.
  7. § 12 Имение родовое и благоприобретенное
  8. Формулировать задание внутренней природе организма следует на языке души
  9. Школьный класс
  10. Одиночки в классе
  11. ПЕРВЫЙ КЛАСС
  12. Разминка антистрессовая, приемы и спецприемы, целевые установки — на естественном языке «внутренней речи».
  13. Разминка антистрессовая, приемы и спецприемы, целевые установки — на естественном языке «внутренней речи».