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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11436792/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 05:08:12  来源:igfitidea点击:

When should I use generics to define relationships between types?

javagenerics

提问by mezamorphic

Getting into a little bit of confusion here when to use generics. I've looked at Java Generics?but still have a few questions.

什么时候使用泛型这里有点混乱。我看过Java泛型?但还有几个问题。

Say I have:

说我有:

public class Honda implements ICar(){
}

public class Opel implements ICar(){
}

Should I use:

我应该使用:

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

or

或者

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

or does it depend on the tasks performed?

还是取决于执行的任务?

Are generics only for aggregation relationships (containers etc); that is, are they just used for collections?

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

采纳答案by Maarten Bodewes

A person is generally not parameterized with a type of car. Only very annoying persons are defined by their car. Persons change cars too (in time). So I would not parameterize the class, if only for the semantics.

一个人通常不会被某种汽车参数化。只有非常讨厌的人才能被他们的车定义。人们也(及时)更换汽车。所以我不会参数化这个类,如果只是为了语义。

Think about what you try to mimic from the real world, before going into such programming details.

在进入这样的编程细节之前,想想你试图从现实世界中模仿什么。

回答by biziclop

The distinction isn't always clearcut but here are a few clues:

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

  1. Try to think of them as "type parameters" (Which they are.) They are associated with the class but they're not necessarily related to it. (Look at the collections framework for example.)
  2. Type parameters can only be used if they don't change throughout an object's lifetime. This sounds quite obvious, but it's a very handy rule to decide when NOT to use generics. (Example is a person who can change cars.)
  3. On the other hand, if not many instances will use the type parameter, if it's too optional, that's not a good idea either. (A lot of people might not have cars at all.)
  1. 尝试将它们视为“类型参数”(它们是什么。)它们与类相关联,但不一定与类相关。(例如,查看集合框架。)
  2. 类型参数只有在对象的整个生命周期都不会改变时才能使用。这听起来很明显,但这是决定何时不使用泛型的一个非常方便的规则。(例如可以换车的人。)
  3. 另一方面,如果没有多少实例会使用类型参数,如果它太可选,那也不是一个好主意。(很多人可能根本没有车。)

And finally, a general thought that I found really useful: if you're unsure, don't be afraid to prototype it. Write the code both ways and check which one looks simpler and easier to comprehend. Show it to someone else without any explanations or maybe wait a day or two and then re-read the code yourself. Then throw the other one away. Throwing away code is good.

最后,我发现一个非常有用的总体想法:如果您不确定,不要害怕对其进行原型设计。以两种方式编写代码,然后检查哪一种看起来更简单、更容易理解。将它展示给其他人而不做任何解释,或者等待一两天,然后自己重​​新阅读代码。然后把另一个扔掉。扔掉代码是好的。

回答by newacct

You need the generics version if you have any methods that take or return anything involving a T, or if it's possible for other people to access your carfield. (Since you didn't show any methods, we can't really tell.)

如果您有任何方法可以获取或返回任何涉及 T 的内容,或者其他人可以访问您的car字段,则您需要泛型版本。(因为你没有展示任何方法,我们真的无法判断。)

For example, with the generics version you can have a method like T someMethod();, then when someone has a Person<Honda>, they know they can get a Hondaback when they call someMethod, rather than some unknown type of car if you didn't have generics.

例如,使用泛型版本,您可以使用类似 的方法T someMethod();,然后当某人拥有 时Person<Honda>,他们知道他们可以Honda在调用 时得到回报someMethod,而不是如果您没有泛型,则可以使用某种未知类型的汽车。

Similarly, with the generics version you can have a method like void anotherMethod(T anotherCar);, then when someone has a Person<Honda>, this forces them to pass a Hondato this method, instead of any car.

类似地,在泛型版本中,您可以使用类似 的方法void anotherMethod(T anotherCar);,然后当有人拥有 时Person<Honda>,这会强制他们将 a 传递Honda给此方法,而不是任何汽车。

So basically, having a generic class allows you to place constraints on uses of the object later on (method calls etc.). If the constructor is the only place that you use T, and you don't need to use T in any methods or fields, then yes, there is no point for it.

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

回答by VSOverFlow

This has to do with using Inheritance versus Composition.

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

Without knowing any other semantics, Composition seems more relevant. A person may change cars, without becoming a different person.

在不知道任何其他语义的情况下,组合似乎更相关。一个人可能会换车,但不会变成另一个人。

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

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

回答by Robert

I'd tend to favor composition (what you're calling dynamic binding), especially in the case you use. A person is not a type of ICar, so using the generics here is kind of weird (to me anyway). I'd use generics as a way of saying "A container for ICar", as in Garage although in that case I might just use a collection type as a variable, or extend the collection type if really needed.

我倾向于支持组合(您称之为动态绑定),尤其是在您使用的情况下。一个人不是 ICar 的一种类型,所以在这里使用泛型有点奇怪(无论如何对我来说)。我会使用泛型来表达“ICar 的容器”,就像在 Garage 中一样,尽管在这种情况下,我可能只使用集合类型作为变量,或者在确实需要时扩展集合类型。

回答by Alonso Dominguez

I'd suggest to focus on semantics first:

我建议首先关注语义:

Providing that you may have a Bmwand a Toyotaclasses implementing the ICarinterface, then make this question: can a Personchange his car or would it be a different person if he does so?

假设您可能有实现接口的aBmw和 aToyotaICar,然后提出以下问题:可以Person更换他的汽车,或者如果他这样做会是另一个人吗?

The generics approach will force you to create a new Personinstance if for some reason you need to change the value of the carattribute from Toyotato Bmwin an existent person instance and thus, this new person will be different from the previous one. Of course, you could create the first Personinstance as Person<ICar>instead of hooking it to a specific car class but, why use generics then?

仿制药的做法将迫使你创建一个新的Person实例,如果由于某种原因,你需要的值更改car属性来自ToyotaBmw在一个存在的人的实例,因此,这种新的人会从以前的不同。当然,您可以创建第一个Person实例,Person<ICar>而不是将其挂接到特定的汽车类,但是,为什么要使用泛型呢?