【问题标题】:GenericClass<T extends SomeClass> where subclasses of SomeClass should behave differently only acts as SomeClassGenericClass<T extends SomeClass> 其中 SomeClass 的子类应该表现不同,只能作为 SomeClass
【发布时间】:2018-12-01 17:05:45
【问题描述】:

我有几个彼此相关的问题。

第一个问题,我有一个接口:

public interface Copiable<T extends Copiable<T>> 
{
    T getCopy();
}

我用来创建实现类的深层副本/克隆。

我有一行类和另一个用于包含它们的类,假设一行类以类开头:

public class Animal implements Copiable<Animal>

并且有另一个类扩展它:

public class Dog extends Animal

理论上(以及我在实践中测试的结果) (Animal object).getCopy() 应该返回一个 Animal 对象, (Dog object).getCopy() 应该返回一个 Dog 对象。

容器类也是通用的,我希望它只包含一个 Animal 或其子类,因为我使用的是 Animal(和 Copiable)方法。所以,我有:

public class Container<T extends Animal>

在 Container 的一种方法中,我有类似的东西:

public void doSomething(List<? extends T> list)
{
    // ...
    T temp = list.get(i).getCopy(); // Gives an error (1)
    List<T> newList = new ArrayList<T>();
    newList.add(list.get(i).getCopy()); // Gives an error (2)
}

(1)“错误:不兼容的类型:Animal不能转换为T”

(2)“错误:没有找到适合添加(动物)的方法”

第二个问题是我在另一个类中使用 Container 类,比如:

public class Zoo
{
    Container<Animal> animals;
    // ...
    void setAnimals(Container<? extends Animal> animals)
    {
        this.animals = animals; // Gives an error (3)
    }
}

(3)“错误:不兼容的类型:Container无法转换为Container”

我有 Zoo 的子类,需要包含 Animals 的子类:

public class PettingZoo extends Zoo
{
    // Using the same container in the parent class
    // Container<Animal> animals
    // It needs to contain Dogs
    // and I need to be able to set Container<Dog> to animals
    // and use animals as a list of Dogs in this class
}

我想了解处理上述 cmets 中所述情况的好方法。

我愿意改变我的设计,我想了解这种行为的原因以及如何解决它。

【问题讨论】:

  • public interface Copiable&lt;T extends Copiable&lt;T&gt;&gt; 为什么不能只使用T
  • public class Animal&lt;T extends Animal&lt;T&gt;&gt; implements Copiable&lt;T&gt;{}public class Dog extends Animal&lt;Dog&gt;{}。这应该可以解决问题
  • &lt;T extends Foo&lt;T&gt;&gt; 几乎总是被那些不完全理解泛型的人弄错。
  • Dog 扩展Animal 的事实意味着Dog 实现Copiable&lt;Animal&gt;,而不是Copiable&lt;Dog&gt;
  • 现有的接口Cloneable 具有相同的用途。深克隆与浅克隆是一种实现选择。通过从 clone() 返回正确的类型,您可以避免出现的大多数泛型内容。

标签: java generics inheritance interface


【解决方案1】:

首先你可能不想使用&lt;T extends Copiable&lt;T&gt;&gt;,因为它并没有真正增加任何价值:

public interface Copiable<T>{
    T getCopy();
}

其次,您必须将泛型参数T 添加到Animal

public class Animal<T extends Animal<T>> implements Copiable<T>{ ... }

这样你就可以定义Dog如下:

public class Dog extends Animal<Dog>{ ... }

还有你的Container 喜欢:

public class Container<T extends Animal<T>> { ... }

最后你必须像这样定义你的Zoo

public class Zoo<T extends Animal<T>> { 
    Container<T> animals;

    ...
}

这允许您只为狗创建PettingZoo

public class PettingZoo extends Zoo<Dog> { ... }

【讨论】:

  • 我一直在努力完成这项工作。我仍然收到所有错误。我遗漏的细节是,还有另一个扩展 Dog 的类,比如 Husky,我实际上将 Dogs 和 Huskys 存储在 Container 中,其中 Container 有一个 List,其中 T 扩展了 Dog。我的类签名是这样的,[class Animal> implements Copiable],[class Dog> extends Animal] 和 [class Husky extends Dog]。我保留了 Copiable 接口,因为我需要每个子类返回自己,我认为这是必要的。字符用完了,你知道吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-06-01
  • 1970-01-01
  • 2018-12-13
  • 2021-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多