在这里使用泛型时会产生一些混乱。我看过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;
}
}
还是取决于执行的任务?
泛型仅用于聚合关系(容器等);那么,它们只是用于收藏吗?
答案 0 :(得分:16)
一个人通常没有参与某种类型的汽车。他们的汽车只定义了非常讨厌的人。人们也会改变汽车(及时)。所以我不会参数化该类,如果仅用于语义。
在进入此类编程细节之前,请考虑一下您尝试从现实世界中模仿的内容。
答案 1 :(得分:11)
区别并不总是明确,但这里有一些线索:
最后,一般认为我觉得非常有用:如果你不确定,不要害怕原型。双向编写代码并检查哪一个看起来更简单,更容易理解。在没有任何解释的情况下将其显示给其他人,或者等待一两天,然后自己重新阅读代码。然后扔掉另一个。抛弃代码很好。
答案 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)
我建议首先关注语义:
假设您可能有Bmw
和Toyota
个类实现ICar
界面,那么请提出以下问题:Person
可以改变他的汽车,还是会改变他的汽车?如果他这样做了另一个人?
如果由于某种原因您需要将Person
属性的值从car
更改为Toyota
,则泛型方法会强制您创建新的Bmw
实例一个现存的人实例,因此,这个新人将与前一个人不同。当然,您可以将第一个Person
实例创建为Person<ICar>
,而不是将其挂钩到特定的汽车类,但是,为什么要使用泛型呢?