PECS: Как преобразовать Потребителя в Производителя?

У меня есть ресторан, который производит еду. На кухне даны тарелки, которые являются Потребителями.

class Food{}
class Bamboo extends Food {}

interface Kitchen {
    void build(List<? super Food> dessert);
}

abstract class Restaurant {
    Kitchen kitchen;

    public Restaurant(Kitchen kitchen) {
        this.kitchen = kitchen;
    }

    List<? extends Food> getMeals() {
        List<Food> food = new ArrayList<>();
        this.kitchen.build(food);
        return food;
    }
}

class PandaKitchen implements Kitchen{

    // Exact signature of the Kitchen
    @Override
    public void build(List<? super Food> plate) {
        // the List IS a consumer of bamboos
        plate.add(new Bamboo());
    }
}

// Bamboo specialized restaurant
class OhPanda extends Restaurant {

    public OhPanda() {
        super(new PandaKitchen());
    }

    // Specialized signature of List<? extends Food>
    @Override
    List<Bamboo> getMeals() {
        List<? super Food> bamboos = new ArrayList<>();
        this.kitchen.build(bamboos);

        // Obviously here, there is no information of having only Bamboos
        return bamboos; // <==== FAIL

        //return (List<Bamboo>) bamboos; // would not compile
    }
}

В последней строке я знаю, что мой ресторан OhPanda производит только бамбук. Какова лучшая практика для конвертации моего List<? super Food> без создания / копирования ArrayList в память?

Более полный Gist написан здесь: https://gist.github.com/nicolas-zozol/8c66352cbbad0ab67474a776cf007427

2 ответа

Решение

Или, может быть, вы могли бы написать печатную версию ресторана и кухни?

package kitchen;

import java.util.ArrayList;
import java.util.List;

class Food{}
class Bamboo extends Food {}

interface Kitchen<F> {
    void build(List<F> dessert);
}

abstract class Restaurant<T> {
    protected Kitchen kitchen;

    Restaurant(Kitchen kitchen) {
        this.kitchen = kitchen;
    }

    List<T> getMeals() {
        List<T> food = new ArrayList<>();
        kitchen.build(food);
        return food;
    }
}

class PandaKitchen implements Kitchen<Bamboo>{

    @Override
    public void build(List<Bamboo> dessert)
    {
        dessert.add(new Bamboo());
    }
}

/** Bamboo specialized restaurant*/
class OhPanda extends Restaurant<Bamboo> {

    OhPanda() {
        super(new PandaKitchen());
    }

    @Override
    List<Bamboo> getMeals() {
        List<Bamboo> bamboos = new ArrayList<>();
        kitchen.build(bamboos);
        return bamboos;
    }
}

Я думаю, что вы неправильно используете нижние ограниченные символы. Вы используете его как обход ограничений на использование символов с верхним ограничением, с которыми вы можете столкнуться, не указав класс своих символов подстановки в своей реализации. Я не думаю, что вы хотите работать с едой и ее супертипами. Вы хотите работать только с продуктами питания и их производными, и вы должны найти решение с помощью "? Extends Food" или даже избавиться от символов подстановки и использовать List

Другие вопросы по тегам