2016-03-09 4 views
2

У меня есть 3 интерфейса:Как создать экземпляр этого класса, параметризованного связным интерфейсом?

public interface IAggregable<TElement extends IAggregable<TElement, TResult>, TResult> { 
    TResult aggregate(TResult intermediateResult); 
} 

public interface IDeeplyCloneable<TElement extends IDeeplyCloneable<TElement>> { 
    TElement deepClone(); 
} 
public interface IContainer<TElement extends IAggregable<TElement, TResult> & IDeeplyCloneable<TElement>, TResult> { 
    TResult aggregateAllElements(); 
    TElement cloneElementAtIndex(int index); 
} 

Тогда есть два класса, которые реализуют эти 2 первые интерфейсы:

public class Person implements IAggregable<Person, Integer>, IDeeplyCloneable<Person> { 
    private int age; 

    public Integer aggregate(Integer intermediateResult) { 
     if (intermediateResult == null) { 
      return age; 
     } 
     return age + intermediateResult; 
    } 

    public Person deepClone() { 
     Person clone = new Person(); 
     clone.age = age; 
     return clone; 
    } 

    @Override 
    public String toString() { 
     return "Person [age=" + age + "]"; 
    } 

} 

и почти точно такой же

public class Car implements IAggregable<Car, Integer>, IDeeplyCloneable<Car> { 

    private int horsepower; 

    public Integer aggregate(Integer intermediateResult) { 
     if (intermediateResult == null) { 
      return horsepower; 
     } 
     return horsepower + intermediateResult; 
    } 

    public Car deepClone() { 
     Car clone = new Car(); 
     clone.horsepower = horsepower; 
     return clone; 
    } 

    @Override 
    public String toString() { 
     return "Car [horsepower=" + horsepower + "]"; 
    } 

} 

тогда, наконец, UselessContainer, которые предполагают реализовать IContainer и иметь возможность удерживать как Person, так и Car и любые другие объекты любого другого класса, которые реализуют IAggregable и IDeeplyCloneable.

public class UselessContainer<TElement extends IAggregable<TElement, TResult> & IDeeplyCloneable<TElement>, TResult> implements IContainer<TElement, TResult> { 

    private ArrayList<TElement> list; 

    public UselessContainer() { 
     this.list = new ArrayList<>(); 
    } 

    public void add(TElement element) { 
     list.add(element); 
    } 

    @Override 
    public TResult aggregateAllElements() { 
     return null; 
    } 

    @Override 
    public TElement cloneElementAtIndex(int index) { 

     return null; 
    } 

    @Override 
    public String toString() { 
     return list.toString(); 
    } 

} 

Вопрос: Как создать объект класса UselessContainer?

Я пробовал: UselessContainer<? extends IAggregable<?, Integer> & IDeeplyCloneable<?>, Integer> container;

+0

Попробуйте 'UselessContainer <Контент Person, Integer>;' или 'UnelessContainer container;'! Если вы хотите разместить разные классы в одном и том же контейнере, тогда ваш дизайн интерфейса неправильный. – fabian

+0

@fabian это то, что я не хочу, я хочу иметь возможность удерживать как автомобиль, так и человека в одном контейнере. –

ответ

0

Вы отметили свой UselessContainer быть привязаны как к IAggregable и IDeeplyCloneable. Посмотрите на знак &, который указывает, что оба интерфейса должны быть реализованы бизнес-объектом для добавления в список.

Для того, чтобы использовать его в коде - просто создать экземпляр UselessContainer без specyfing конкретных типов дженерики:

UselessContainer uc = new UselessContainer(); 
    uc.add(new Person()); // works! 
    uc.add(new Integer(1)); // won't compile 
    uc.add(new Car()); // works! 

Я просто попытался его в своем редакторе и он работает (JDK8).

EDIT: Вы можете создать упаковочную класс:

class SimpleContainer { 
    public <TElement extends IAggregable<TElement, TResult> & IDeeplyCloneable<TElement>, TResult> void add(TElement el) { 
     UselessContainer<TElement, TResult> uc = new UselessContainer<>(); 
     uc.add(el); 
    } 
} 

и использовать его:

SimpleContainer sc = new SimpleContainer(); 
     sc.add(new Person()); 
+0

Я уже делал это, и он работал нормально, но я хотел явно параметризовать 'UselessContainer'. –

+0

Единственное, что я имею в виду, это создать класс упаковки с помощью метода, я отредактировал свой ответ выше ^. Какие явные параметры дадут контейнеру? Что такое бизнес-кейс? – mlewandowski

0

У вас есть 2 условия, которые вы хотите встретиться для UselessContainer<A, B> (ну сократить это U<A,B>) :

(1) Car s может быть добавлен в U<A, B>

(2) Person ы могут быть добавлены к U<A, B>

выполняют обе (1) и (2) невозможно, что может быть доказано с помощью косвенного доказательства:

Предположим, выполняя оба условия можно было ,

Подпись add is add(TElement element) method and TElement extends IAggregable<TElement, TResult>.

Из (1) и Car implements IAggregable<Car, Integer> мы можем поэтому вывести A=Car.

И из (2) и Person implements IAggregable<Person, Integer> поэтому можно сделать вывод A=Person.

Объединив эти 2 результата, получим Car=Person, что, очевидно, неверно. Это противоречие завершает доказательство.


Это означает, что вам необходимо изменить ограничения на параметры типа или использовать необработанный тип.

Смежные вопросы