2013-10-09 3 views
2

Я пытаюсь переопределить метод, возвращающий тип как список в подклассе, как показано ниже, из-за проблемы с генериками я не могу это сделать в своем подклассе. Я не могу изменить свой код суперкласса, так как я могу решить проблему? любой может направить меня ... большое спасибо заранее.Как переопределить общий тип возвращаемого списка в java

Супер-классы, которые не могут быть обновление:

public class Animal { 
      private String legs; 
    } 

public class TestSuper { 

    public List<Animal> addAnimals() { 
     return animals; 
    } 
} 

Суб классы:

public class Dog extends Animal { 
     private String sound; 
    } 

public class TestSub extends TestSuper { 

    public List<Dog> addAnimals() { --> I need to override this method but want return type as List of dogs 
     return null; 
    } 
} 
+0

Вы можете переопределить тип возвращаемого значения только с помощью типа, совместимого с назначением. Однако дженерики не ковариантны. 'Список ' не является подтипом 'List '. См. [Эту тему] (http://stackoverflow.com/questions/14694852/can-overridden-methods-differ-in-return-type). –

ответ

7

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

Если бы вы были в состоянии обновить супер классов:

В TestSuper, вы бы использовать public List<? extends Animal> addAnimals() вместо public List<Animal> addAnimals().

Что другое решение (ы) у вас есть:

Вы могли бы использовать такой метод полезности:

@SuppressWarnings("unchecked") 
public static <T extends Animal> List<T> cast(List<Animal> animals, Class<T> subclass) { 
    List<T> out = new ArrayList<T>(); 
    for (Animal animal : animals) { 
     if (!subclass.isAssignableFrom(animal.getClass())) { 
      // the "animal" entry isn't an instance of "subclass" 
      // manage this case however you want ;) 
     } else { 
      out.add((T) animal); 
     } 
    } 
    return out; 
} 

Затем позвонить:

List<Dog> dogs = TheClassNameYouChose.cast(animals, Dog.class); 
+0

Спасибо за ваш ответ, но у меня есть эта опция в моем проекте, из-за этой причины, ожидая предложений :( – Satya

+0

@Satya Смотрите мое обновление, возможно, это может помочь. – sp00m

+0

хотел использовать addAnimals(), который есть в супер class ... следовательно, я пытаюсь переопределить – Satya

0

Вы бы нужно чтобы TestSuper использовал дженерики, чтобы действительно сделать эту работу правильно.

TestSuper<T extends Animal> { 

    public List<T> addAnimals() { 

    } 
} 

TestSub extends TestSuper<Dog> { 


} 
1

Если Dog подкласс Animal, вы могли бы сделать

Следующая подпись:

public List<? extends Animal> addAnimals() 

Затем сделать

public List<Dog> addAnimals() 

в классе к югу.

Или вы могли бы сделать супер класс общим <T> и класс реализации <Dog>

2

Вы не можете изменить общий вид списка для подтипа этого общего типа. Проблема в том, что ссылка на любой экземпляр может быть подтипом этого экземпляра. Так что давайте посмотрим на этот пример

SuperType sup = new SubType(); 
sup.getAnimals().add(new Cat()); 
//adding cat is possible because getAnimals() returns List<Animal> 

Таким образом, вы бы добавить Cat в список, который должен содержать только Dogs, что неправильно.


Также в переопределенном методе вы не можете изменить общий тип списка список с надтипом этого общего типа (например, List<Dog> к List<Animal>). Зачем?Давайте посмотрим на этот пример

SuperType sup = new SubType(); 
Dog d = sup.getAnimals().get(0); 

В подтипа мы имеем список животных, так что возможно, что get(0) вернется Cat.


Если вы можете изменить код в классах, то попробуйте, может быть, этот подход

class Super<T extends Animal> { 
    public List<T> addAnimals() { 
     return null; 
    } 
} 

class Sub extends Super<Dog> { 

    @Override 
    public List<Dog> addAnimals() { 
     return null; 
    } 
} 
0

Это не представляется возможным. Контракт супер класс говорит, что если у вас есть:

class Animal {} 
class Dog extends Animal {} 
class Cat extends Animal {} 

Следующий код должен быть действительным:

TestSuper test = new AnySubclassOfTestSuper(); // including TestSub! 
test.addAnimals().add(new Cat()); 

переопределения в TestSub классе нарушило бы, что, так как вы не можете добавить Cat - List<Dog>. Поскольку это было бы нарушением довольно фундаментального принципа систем объектно-ориентированного типа, вы не найдете идеального обходного пути для этого ограничения.

Предложения по замене суперкласса на использование List<? extends Animal> будут работать, потому что вы не можете добавить что-либо в этот список.

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