我什么时候应该使用泛型来定义类型之间的关系?

时间:2012-07-11 16:06:22

标签: java generics

在这里使用泛型时会产生一些混乱。我看过Java Generics?,但仍有几个问题。

说我有:

public class Honda implements ICar(){
}

public class Opel implements ICar(){
}

我应该使用:

public class Person{
    ICar car;
    .
    .
    public Person (ICar c){
        car = c;
    }
}

public class Person<T extends ICar>{
    T car;
    .
    .
    public Person(T c){
        car = c;
    }
}

还是取决于执行的任务?

泛型仅用于聚合关系(容器等);那么,它们只是用于收藏吗?

6 个答案:

答案 0 :(得分:16)

一个人通常没有参与某种类型的汽车。他们的汽车只定义了非常讨厌的人。人们也会改变汽车(及时)。所以我不会参数化该类,如果仅用于语义。

在进入此类编程细节之前,请考虑一下您尝试从现实世界中模仿的内容。

答案 1 :(得分:11)

区别并不总是明确,但这里有一些线索:

  1. 尝试将它们视为“类型参数”(它们是什么。)它们与类相关联,但它们不一定与它相关。 (例如,查看集合框架。)
  2. 只有在整个对象的生命周期内不改变类型参数时,才能使用它们。这听起来很明显,但决定何时不使用泛型是一个非常方便的规则。 (例如可以改变汽车的人。)
  3. 另一方面,如果没有多少实例将使用type参数,如果它太可选,那也不是一个好主意。 (很多人可能根本没有车。)
  4. 最后,一般认为我觉得非常有用:如果你不确定,不要害怕原型。双向编写代码并检查哪一个看起来更简单,更容易理解。在没有任何解释的情况下将其显示给其他人,或者等待一两天,然后自己重​​新阅读代码。然后扔掉另一个。抛弃代码很好。

答案 2 :(得分:8)

如果您有任何方法可以接受或返回任何涉及T的内容,或者其他人可以访问您的car字段,则您需要使用泛型版本。 (由于你没有显示任何方法,我们无法说出来。)

例如,对于泛型版本,您可以使用T someMethod();之类的方法,然后当某人拥有Person<Honda>时,他们知道当他们调用{Honda时可以获得someMethod 1}},而不是一些未知类型的汽车,如果你没有泛型。

同样,对于泛型版本,您可以使用void anotherMethod(T anotherCar);之类的方法,然后当某人有Person<Honda>时,这会强制他们将Honda传递给此方法,而不是任何方法车。

基本上,拥有泛型类允许您稍后对对象的使用施加约束(方法调用等)。如果构造函数是你使用T的唯一地方,并且你不需要在任何方法或字段中使用T,那么是的,没有必要。

答案 3 :(得分:4)

这与使用继承与组合有关。

在不知道任何其他语义的情况下,Composition似乎更具相关性。一个人可以改变汽车,而不会成为一个不同的人。

http://www.artima.com/objectsandjava/webuscript/CompoInherit1.html http://en.wikipedia.org/wiki/Composition_over_inheritance

答案 4 :(得分:1)

我倾向于赞成合成(你称之为动态绑定),特别是在你使用的情况下。一个人不是一种ICar,所以在这里使用仿制药有点奇怪(无论如何)。我使用泛型作为说“ICar的容器”的方式,就像在Garage中一样,尽管在这种情况下我可能只使用集合类型作为变量,或者如果真的需要扩展集合类型。

答案 5 :(得分:0)

我建议首先关注语义:

假设您可能有BmwToyota个类实现ICar界面,那么请提出以下问题:Person可以改变他的汽车,还是会改变他的汽车?如果他这样做了另一个人?

如果由于某种原因您需要将Person属性的值从car更改为Toyota,则泛型方法会强制您创建新的Bmw实例一个现存的人实例,因此,这个新人将与前一个人不同。当然,您可以将第一个Person实例创建为Person<ICar>,而不是将其挂钩到特定的汽车类,但是,为什么要使用泛型呢?