Есть ли способ с помощью Generics Java принять параметр Generic, который требует реализации 2 интерфейсов? - PullRequest
4 голосов
/ 17 июля 2009

Скажите, у меня есть этот код -

public interface ParentInterface1 {
    public List<? extends ChildInterface1> getChildren();
    public void setChildren(List<? extends ChildInterface1> children);
}
public interface ParentInterface2 {
    public List<? extends ChildInterface2> getChildren();
    public void setChildren(List<? extends ChildInterface2> children);
}
public interface ChildInterface1 {
    public String getField();
    public void setField(String field);
}
public interface ChildInterface2 {
    public String getField();
    public void setField(String field);
}
public class LParentImpl implements ParentInterface1, ParentInterface2 {
    private List<ChildImpl> list;
    public List<ChildImpl> getChildren() {
        return list;
    }
    public void setChildren(List<... wants to accept ChildImpl, which 
                                   implements ChildInterface1 & ChildInterface2> children) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
}
public class ChildImpl implements ChildInterface1, ChildInterface2 {
    private String field;
    public String getField() {
        return field;
    }
    public void setField(String field) {
        this.field = field;
    }
}

Есть ли способ заставить setChildren () в классе ParentImpl работать без полного удаления универсальной типизации из интерфейса и реализации?

Я бы хотел сделать что-то вроде -

public void setChildren(List<? extends ChildInterface1 & ChildInterface2> children) 

Этот вид структуры интерфейса / реализации действителен для неуниверсальных типов, но кажется, что какой-то аспект стирания универсальных типов может сделать это невозможным? Или мне не хватает магического синтаксиса?

Редактировать: Использование списка <? extends ChildInterface1 & ChildInterface2> выдает эту ошибку компиляции -

...\ParentImpl.java:20: > expected
    public void setChildren(List<? extends ChildInterface1 & ChildInterface2> children) {

Ответы [ 4 ]

11 голосов
/ 17 июля 2009

Вы можете указать метод, который принимает объект, который реализует эти два интерфейса, как это:

public <T extends IFirst & ISecond> void doSomething(T obj) {}

Однако в вашем примере это не будет иметь большого значения, поскольку оба ваших дочерних интерфейса задают одни и те же методы.

4 голосов
/ 17 июля 2009

Ваша проблема не имеет смысла.

ParentInterface1.setChildren принимает List<ChildInterface1>. Поэтому так много LParentImpl.setChildern, но вы пытаетесь ограничить это так, чтобы это не так.

Возможно, вы захотите сказать, параметризация ParentInterface1 / 2, но я бы посоветовал избегать множественного наследования интерфейса везде, где это возможно (не только там, где задействованы обобщенные элементы).

4 голосов
/ 17 июля 2009

Вы можете сделать это:

public class MyClass<T extends ChildInterface1 & ChildInterface2> { ... }

Взгляните на Универсальные символы Java с несколькими классами

0 голосов
/ 17 февраля 2010

Это не ответ, но я должен поблагодарить Йорна за его ответ!

Я наткнулся на эту ветку, пытаясь сделать именно то, что дал мне ваш ответ (хотя он не отвечает на исходный вопросник). Я пытался сделать это:

public static interface Displayable
    extends Identifiable, Nameable { }

public void print(Displayable obj) {
    System.out.println("[" + obj.getIdentity() + "] " + obj.getName());
}

, который не работает, потому что объект, который я передаю, не реализует Displayable, но не Nameable и Identifiable отдельно.

Используя технику Йорна, я делаю это:

public <T extends Identifiable & Nameable> void print(T obj) {
    System.out.println("[" + obj.getIdentity() + "] " + obj.getName());
}

и работает безупречно!

Надеюсь, это будет полезно другим, у которых возникла такая же проблема, как у меня (и наткнулся на эту ветку).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...