我见过很多人建议您将通用类型封装在离您的域更近的类中,例如Steve和Nat在Growing Object-Oriented Software, Guided by Tests中建议:
我们的经验法则是我们试图用泛型来限制传递类型[...]。特别是当应用于集合时,我们将其视为一种复制形式。这是一个暗示,应该将一个域概念提取到一个类型中。
一般来说,什么时候做这样的事情是个好主意..
class PersonList : List<Person>
..而不是直接使用List<Person>
?
答案 0 :(得分:4)
您正在寻找的是Java或C#的typedef
运算符。
不幸的是,子类化方法不能替代typedef
。
以下文章"Java theory and practice: The pseudo-typedef antipattern"详细解释了原因。
我将在这里逐字复制该文章的结论:
伪typedef反模式的动机很简单 足够 - 开发人员想要一种定义更紧凑类型的方法 标识符,特别是作为泛型使标识符更多 冗长。问题是这个成语之间产生了紧密的联系 使用它的代码和代码的客户端,禁止重用。您 可能不喜欢泛型类型标识符的详细程度,但这是 不是解决问题的方法。
答案 1 :(得分:2)
我不同意这种哲学。 List<Person>
类型就像PersonList
一样。人员列表的域概念也被封装在其中。如果你问我,最好尽可能多地使用泛型,除非使用它们限制你(见下文)或使代码难以理解。例如,对PersonList
起作用的函数将比List<Person>
上的函数更难概括,如果您甚至注意到它正在执行一般操作。
也就是说,特别是在Java中,对泛型的限制使得它们的吸引力降低了很多。由于类型擦除,当涉及静态方法/类型成员时,您无法充分利用泛型,并且您可能需要提取非通用的特定类型以便能够将其用于某些事物。最重要的是,在Java中,您需要在许多情况下提取特定类型,如果这样可以保持类型安全。
答案 2 :(得分:1)
因为保留类型参数不是真的DRY。考虑这个课程:
class Muffin {
List<string> _peopleWhoLikeMuffins = new List<string>();
public Muffin(List<string> peopleWhoLikeMuffins) {
_peopleWhoLikeMuffins = peopleWhoLikeMuffins);
}
public void AddMuffinLiker(string p) {
_peopleWhoLikeMuffins.Add(p);
}
}
它非常短,只包含基本功能,但我不得不使用string
- genertic类型参数 - 四次。它将永远是相同的。如果我决定稍后更改类型,我将不得不更换所有四个类型。
在现实世界的场景中,我们说的是数百个,而不是4个。所以,总是把它封装起来并不是一件容易的事,但这绝对值得考虑。
现在,我的例子不是很好(而且不仅仅是因为愚蠢的名字),但是你明白了 - 你将有很多字段和变量声明和实例化,每次你必须通过一个类型参数,在整个过程中始终是相同的 代码库,除非你的其他类也是通用的。
这样做的另一个好处是,如果您需要在集合中添加一些额外的状态/行为,那么您的工作就会少得多。
尽管如此,我自己并不经常使用这种抽象。