русс | укр

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

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

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

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


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

Параметризованные интерфейсы


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


Параметризация работает и с интерфейсами. Например, класс, создающий объекты, называется генератором. В сущности, генератор представляет собой специализированную версию паттерна «метод-фабрика», но при обращении к нему никакие аргументы не передаются, тогда как метод-фабрика обычно получает аргументы. Генератор умеет создавать объекты без дополнительной информации.

Обычно генератор определяет всего один метод — тот, который создает объекты. Назовем его next() и включим в стандартный инструментарий:

//: net/mindview/util/Generator.java

// Параметризованный интерфейс

package net.mindview.util;

public interface Generator<T> {

T next(); }

Возвращаемое значение метода next() параметризовано по типу Т. Как видите, механизм параметризации работает с интерфейсами почти так же, как с классами.

Чтобы продемонстрировать, как работает реализация Generator, мы воспользуемся иерархией классов, представляющих разные виды кофе:

//: generics/coffee/Coffee.java

package generics.coffee;

public class Coffee {

private static long counter = 0;

private final long id = counter++;

public String toString() {

return getClass().getSimpleName() + " " + id;

}

}

 

//: generics/coffee/Latte.java

package generics.coffee;

public class Latte extends Coffee {}

 

//: generics/coffee/Mocha.java

package generics.coffee;

public class Mocha extends Coffee {}

 

//: generics/coffee/Cappuccino.java

package generics.coffee;

public class Cappuccino extends Coffee {}

 

//: generics/coffee/Americano.java

package generics.coffee;

public class Americano extends Coffee {}

 

//: generics/coffee/Breve.java

package generics.coffee;

public class Breve extends Coffee {}

Теперь мы можем реализовать интерфейс Generator<Coffee>, который создает случайные типы объектов из иерархии Coffee:



//: generics/coffee/CoffeeGenerator.java

// Генератор случайных объектов из иерархии Coffee

package generics.coffee;

import java.util.*;

import net.mindview.util.*;

 

public class CoffeeGenerator

implements Generator<Coffee>, Iterable<Coffee> {

private Class[] types = { Latte.class, Mocha.class,

Cappuccino.class, Americano.class, Breve.class, };

private static Random rand = new Random(47);

public CoffeeGenerator() {}

//Для перебора

private int size = 0;

public CoffeeGenerator(int sz) { size = sz; }

public Coffee next() {

try {

return (Coffee)

types[rand.nextInt(types.length)].newInstance();

// Сообщение об ошибках во время выполнения:

} catch(Exception e) {

throw new RuntimeException(e);

}

}

class CoffeeIterator implements Iterator<Coffee> {

int count = size;

public boolean hasNext() { return count > 0; }

public Coffee next() {

count--;

return CoffeeGenerator.this.next();

}

public void remove() {// He реализован

throw new UnsupportedOperationException();

}

};

public Iterator<Coffee> iterator() {

return new CoffeeIterator();

}

public static void main(String[] args) {

CoffeeGenerator gen = new CoffeeGenerator();

for(int i = 0; i < 5; i++)

System.out.println(gen.next());

for(Coffee c : new CoffeeGenerator(5))

System.out.println(c);

}

}

<spoiler text="Output:">

Americano 0

Latte 1

Americano 2

Mocha 3

Mocha 4

Breve 5

Americano 6

Latte 7

Cappuccino 8

Cappuccino 9

</spoiler> Параметризованный интерфейс Generator гарантирует, что next() вернет параметр типа. CoffeeGenerator также реализует интерфейс Iterable и поэтому может использоваться в синтаксисе foreach. Аргумент, по которому определяется момент прекращения перебора, передается при вызове второго конструктора.

А вот как выглядит другая реализация Generator<T>, предназначенная для получения чисел Фибоначчи:

//: generics/Fibonacci.java

// Построение чисел Фибоначчи

import net.mindview.util.*;

 

public class Fibonacci implements Generator<Integer> {

private int count = 0;

public Integer next() { return fib(count++); }

private int fib(int n) {

if(n < 2) return 1;

return fib(n-2) + fib(n-1);

}

public static void main(String[] args) {

Fibonacci gen = new Fibonacci();

for(int i = 0; i < 18; i++)

System.out.print(gen.next() + " ");

}

}

<spoiler text="Output:">

1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584

</spoiler> Хотя и внутри, и снаружи класса мы работаем с int, в параметре типа передается Integer. В этом проявляется одно из ограничений параметризации в языке Java: примитивные типы не могут использоваться в качестве параметров типа. Впрочем, в Java SE5 была добавлена удобная автоматическая упаковка (распаковка) для перехода от примитивных типов к объектным «оберткам», и наоборот. Можно сделать следующий шаг вперед и создать генератор чисел Фибоначчи с реализацией Iterable. Конечно, можно изменить реализацию класса и добавить интерфейс Iterable, но исходные коды не всегда находятся в вашем распоряжении, и вообще там, где это возможно, лучше обойтись без их модификации. Вместо этого мы воспользуемся «адаптером» для получения нужного интерфейса (этот паттерн уже упоминался ранее в книге). Существует несколько вариантов реализации адаптеров. Например, для получения адаптируемого класса можно воспользоваться наследованием:

//: generics/IterableFibonacci.java

// Adapt the Fibonacci class to make it Iterable.

import java.util.*;

 

public class IterableFibonacci

extends Fibonacci implements Iterable<Integer> {

private int n;

public IterableFibonacci(int count) { n = count; }

public Iterator<Integer> iterator() {

return new Iterator<Integer>() {

public boolean hasNext() { return n > 0; }

public Integer next() {

n--;

return IterableFibonacci.this.next();

}

public void remove() { // Not implemented

throw new UnsupportedOperationException();

}

};

}

public static void main(String[] args) {

for(int i : new IterableFibonacci(18))

System.out.print(i + " ");

}

}

<spoiler text="Output:">

1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584

</spoiler> Для использования IterableFibonacci в синтаксисе foreach мы передаем конструктору границу, чтобы метод hasNext() знал, когда следует возвращать false.



<== предыдущая лекция | следующая лекция ==>
Класс стека | Параметризованные методы


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


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

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

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


 


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

 
 

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

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