`
alanwu
  • 浏览: 200856 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

泛型参数 V.S. 抽象类型成员

阅读更多

 

 

by Bill Venners
October 7, 2009

http://www.artima.com/weblogs/viewpost.jsp?thread=270195

 

摘要:

在这篇博客中,作者试图回答Scala编程中一个共同的问题:在Scala API设计时,什么时候用泛型参数,什么时候用抽象类型成员。

 

---------------------------------------------------------------------------------------------

学习Scala建一个抽象类型模型的时,一个普遍的问题是如何决定使用泛型参数,还是抽象类型成员。对于不熟悉这两则区别的人来说,Scala的泛型参数有点像Java的泛型参数,只是Java用尖括号,而Scala用方括号。

 

Java泛型 

interface Collection<T> {
    // ...
}
 

 

Scala泛型使用方括号 

// Type parameter version
trait Collection[T] {
  // ..

}
 

Scala的抽象类型成员(Abstract type members)没用和Java等同的。 两个语言中,类,接口(Java),特征(Scala)都可以有方法和字段作为成员。Scala的类或特征(trait)可以有类型成员,下面例子是抽象类型成员:

 

// Type member version

trait Collection {
  type T
  // ...
}

 

这两种情况,抽象类型都可以在子类中具体化。下面的例子中子类用String具体化了类型参数T:

// Type parameter version

trait StringCollection extends Collection[String] {
  // ...
}

 

或者在子类内部具体化类型参数T:

 

// Type member version
trait StringCollection extends Collection {
  type T = String
  // ...
}

 

这看上去,事实上也是,有两种不同的方法达到同一个目的。那么我们怎么做选择呢?我在采访Martin Odersky(Scala创始人)的时候问了这个问题,他最先解释了同时有这两种方法是正交的。

Martin Odersky 写道
总是有两种对抽象的观念:
参数化和抽象成员。Java也有可以同时有这两个,但这取决于你想抽象什么。
用Java你可以有抽象方法,但你不能将方法当作参数。你不能有抽象字段,但可以将传递参数。简单将你可以没用抽象类型成员,但你可以将具体的类型当参数。所以用Java你也可以有这三种方式,只是你在做不同类型的事情时的抽象原则有所不同。你可以说这些差异是简直是专制。

我们试图让Scala在抽象方面变得完全和正交。我们决定对所有这三种成员(类型,字段,方法)的抽象有统一的构造原则。你可以像值参数那样有抽象字段。你可以像参数一样传递方法(或叫函数),或者你能抽象他们。你可以像参数那样具体化类型,或者抽象他们。我们可以在概念上为其他建立一个模型(we can model one in terms of the other)。至少在原则上,我们能对每个不同的参数化做统一的OO抽象。所以在一定意义上说,Scala是更充分和正交(orthogonal )的语言。

 

他同时解释了抽象类型成员和泛型参数在实际应用中的不同:

 

Martin Odersky 写道
在实际应用中,当你在不同时候使用类型参数时,会暴露参数,甚至参数边界(bounds of parameters)。在1998年ECOOP,Kim Bruce, Phil Wadler和我在一篇文章中展示了当你在不知道的情况下增加的东西会编程二次方。所以这是个很好的理由不要参数,而使用抽象成员,因为他们不会给你成倍的增加。
 当Martin给我这个答案的时候,我并不确认是不是真的理解了他所讲的,但是现在我可以给出更多的不同点。我总是倾向于使用泛型参数,因为我来自C++和Java背景,更加熟悉类型参数化和类型成员。尽管如此,我遇到一个设计问题,我使用了抽象类型成员解决了问题,而不是泛型类型参数。
 这个问题是当我设计ScalaTest时想提供traits让用户写的测试能传入特定的对象。这可以给大家选择使用函数编程方式写测试,而不只是像命令式的JUnit中的setUp,tearDown方法。要提供这种选择,我需要让用户能通过具体类型参数或者成员来指示特定对象的类型。换句话说,我要在ScalaTest API中提供这样的trait.
// Type parameter version
trait FixtureSuite[F] {
  // ...
}
或者:
// Type member version
trait FixtureSuite {
  type F
  // ...
}
一种情况是,F是特定参数穿入的,suite的子类需要提供具体类型。这里的测试具体子类需要将StringBuilder传入到每个测试,使用类型参数达到这个目的:
// Type parameter version
class MySuite extends FixtureSuite[StringBuilder] {
  // ...
}
 同时另一个例子是将StringBuilder当作抽象类型成员值传递给每个测试:
// Type member version
class MySuite extends FixtureSuite {
  type F = StringBuilder
  // ...
}
 
So far there's not much difference. However, one other use case I had is that I wanted to allow people to create traits that provide a concrete definition for the fixture type and could be mixed into suite classes. This would allow users to encode commonly used fixtures into helper traits that could be mixed into any of their suite classes that need them. This is where a difference showed up. Here's how you'd write that trait using the generic type parameter approach:



分享到:
评论
1 楼 alanwu 2009-10-17  
还没翻完,希望在下周翻译完毕。

相关推荐

    csharp language specification v3.0 pdf

    泛型允许编写类型安全的代码,通过使用类型参数来定义类或方法,可以在运行时确定具体类型。 ```csharp class GenericClass&lt;T&gt; { ... } // 泛型类 void GenericMethod(T item) { ... } // 泛型方法 ``` ###### ...

    标准模板库STL(Standard Template Library)指南

    基于这一洞察,Stepanov提出了一种思想:通过抽象化的方式实现算法,可以在不影响效率的前提下提高其通用性。 ##### 1.2 STL 历史 1985年,Alexander Stepanov开始了他对模板库的探索,最初是在Ada语言环境下开发...

    java单词表1 .docx

    6. **Generic[dʒəˈnerɪk]**:泛型是一种编写类型安全的代码的方式,可以在编译时检查类型。 ### 第十章:数据库操作 1. **JDBC**:Java Database Connectivity,一种用于执行SQL语句的Java API。 2. **...

    java单词表

    3. ClassCastException [klɑ:s][kɑ:st][ɪkˈsepʃn]:类类型转换异常,指的是在类型转换时出现的错误。 4. Upcasting [ʌp'kɑ:stɪŋ]:向上转型,指的是将子类对象转换为父类对象。 5. Downcasting [daun][ˈk...

    java常用词汇汇总

    - **用途**:Java中的泛型允许在类、接口和方法中使用类型参数,从而实现类型安全的代码重用。 #### goto (保留字) 跳转 - **中文释义**:跳转 - **用途**:虽然`goto`是Java中的保留字,但实际上并未被用作关键字...

    Visual Basic 2012 Programmer's Reference VB2012程序员参考手册

    - 如何使用泛型约束限定类型参数的范围。 - 泛型容器类的设计思路和实现方法。 #### 四、环境交互篇 ##### 第四部分:与环境交互 **第27章:打印** - **概述**:介绍Visual Basic 2012中打印功能的实现方法。 ...

    2011东南大学计算机学院研究生复试笔试试题

    函数模板使用关键字`template`定义,并包含一个类型参数列表。 - **函数模板实例化**:函数模板实例化是指根据实际使用的类型来创建具体的函数版本的过程。每当使用特定类型调用函数模板时,编译器就会自动实例化该...

    java_编程常用英语单词_解释.pdf

    - **解释**: “Generic”是指Java中的一种类型参数化机制,允许创建可以用于多种类型的通用类或方法。这提高了代码的复用性和灵活性。 #### 39. Goto (跳转) - **拼音**: ['ɡoʊtuː] - **解释**: “Goto”是Java...

    黑马JavaSE基础+进阶重难点精华版复习资料

    - **类型参数**:泛型中的类型参数,如`T`、`E`等。 #### 9. 异常处理:Lambda表达式与Stream流 - **基础知识**: - **异常处理**:处理程序执行过程中可能出现的错误。 - **Lambda表达式**:简化函数式接口...

    java_编程常用英语单词_解释

    通过使用泛型,可以编写灵活且可重用的代码,同时避免类型转换错误。 #### Goto (保留字) 跳转 - **发音**:['ɡəutuː] - **定义**:Goto 是Java中的一个保留字,尽管目前在Java中并没有直接使用,但它保留用于...

Global site tag (gtag.js) - Google Analytics