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

时间:2011-08-30 10:07:04

标签: c# java generics

我见过很多人建议您将通用类型封装在离您的域更近的类中,例如Steve和Nat在Growing Object-Oriented Software, Guided by Tests中建议:

  

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

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

class PersonList : List<Person>

..而不是直接使用List<Person>

3 个答案:

答案 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个。所以,总是把它封装起来并不是一件容易的事,但这绝对值得考虑。

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

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

尽管如此,我自己并不经常使用这种抽象。