什么时候应该封装generics类型?

我见过很多人建议你应该用类更接近你的域封装generics类型,例如Steve和Nat在增长面向对象软件中的建议,在测试的指导下 :

我们的经验法则是我们试图用generics来限制传递类型[…]。 特别是当应用于集合时,我们将其视为一种复制forms。 这是一个暗示,应该将一个域概念提取到一个类型中。

一般来说,什么时候做这样的事情是个好主意..

class PersonList : List 

..而不是直接使用List

您正在寻找的是Java或C#的typedef运算符。

不幸的是,子类化方法不是typedef的良好替代品。

以下文章“Java理论与实践:伪类型反模式”详细解释了原因。

我将在这里逐字复制该文章的结论:

伪typedef反模式的动机很简单 – 开发人员想要一种方法来定义更紧凑的类型标识符,特别是因为generics使类型标识符更加冗长。 问题是这个习惯用法在使用它的代码和代码的客户端之间产生紧密耦合,从而抑制了重用。 您可能不喜欢generics类型标识符的详细程度,但这不是解决它的方法。

我不同意这种哲学。 List是一个类似PersonList的类型。 人员列表的域概念也被封装在其中。 如果你问我,最好尽可能多地使用generics,除非使用它们限制你(见下文)或使代码难以理解。 例如,如果你甚至注意到它正在做一些普通的事情,那么在PersonList上工作的函数将比在List上工作的函数更难推广。

也就是说,特别是在Java中,generics的限制使得它们的吸引力降低了很多。 由于类型擦除,当涉及静态方法/类型成员时,您无法充分利用generics,并且您可能需要提取非通用的特定类型以便能够将其用于某些事物。 最重要的是,在Java中,您需要在许多情况下提取特定类型,如果这样可以保持类型安全。

因为保留类型参数不是真的DRY。 考虑这个课程:

 class Muffin { List _peopleWhoLikeMuffins = new List(); public Muffin(List peopleWhoLikeMuffins) { _peopleWhoLikeMuffins = peopleWhoLikeMuffins); } public void AddMuffinLiker(string p) { _peopleWhoLikeMuffins.Add(p); } } 

它真的很短,只包含基本function,但我不得不使用string – genertic类型参数 – 四次。 它总是一样的。 如果我决定稍后更改类型,我将不得不更换所有四个出现的类型。

在现实世界的场景中,我们谈论的是数百个,而不是4个。所以,总是把它封装起来并不是一件容易的事,但它绝对值得考虑。

现在,我的例子不是很好(不仅仅是因为愚蠢的名字),但你明白了 – 你将有很多字段和变量声明和实例化,每次你必须传递一个类型参数除非您的其他类也是通用的,否则在整个代码库中始终是相同的。

这样做的另一个好处是,如果您需要在集合中添加一些额外的状态/行为,那么您的工作量会少得多。

总而言之,我自己并不经常使用这种抽象。