Fre*_*ind 3 generics scala lift traits
当我阅读Liftweb的源代码时,我发现了一些特征声明:
trait ValueHolder {
type ValueType
def get: ValueType
}
trait PValueHolder[T] extends ValueHolder {
type ValueType = T
}
Run Code Online (Sandbox Code Playgroud)
我的问题是,对于以下两个特征声明:
trait ValueHolder {
type ValueType
}
trait ValueHolder[T] {
}
Run Code Online (Sandbox Code Playgroud)
我认为它们彼此相同,但它们之间有什么区别吗?一个人可以做或提供另一个人不能做的事情吗?
第一个被调用abstract type member,第二个是类似于Java泛型,但是没有完全相同.这是实现相同目标的两种不同方式.正如Martin Odersky所解释的那样是他的访谈,同时拥有抽象类型成员和泛型类型参数的一个原因是正交性:
一直有两种抽象概念:参数化和抽象成员.在Java中你也有两者,但它取决于你抽象的东西.在Java中,您有抽象方法,但不能将方法作为参数传递.您没有抽象字段,但可以将值作为参数传递.同样,您没有抽象类型成员,但您可以将类型指定为参数.所以在Java中你也有这三个,但是你可以用什么抽象原理来区分什么样的东西.你可以说这种区别是相当武断的.
我们在Scala中所做的是尝试更完整和正交.我们决定为所有三类成员制定相同的建筑原则.所以你可以有抽象字段和值参数.您可以将方法(或"函数")作为参数传递,也可以对它们进行抽象.您可以将类型指定为参数,也可以对它们进行抽象.我们从概念上得到的是我们可以用另一个来模拟一个.至少在原理上,我们可以将各种参数化表达为面向对象的抽象形式.从某种意义上说,你可以说Scala是一种更正交和完整的语言.
他还描述了抽象类型成员和可在实践中显示的泛型类型参数之间的区别:
但实际上,当你使用带有许多不同东西的类型参数化时,它会导致参数爆炸,通常,在参数范围内.在1998年的ECOOP上,Kim Bruce,Phil Wadler和我有一篇论文,我们展示了当你增加你不知道的东西的数量时,典型的程序会以二次方式增长.所以有很好的理由不做参数,而是有这些抽象的成员,因为他们没有给你这个二次爆炸.
我认为比尔维纳斯(ScalaTest的创建者)给出了一个很好的例子:
// Type parameter version
trait FixtureSuite[F] {
// ...
}
Run Code Online (Sandbox Code Playgroud)
和
// Type member version
trait FixtureSuite {
type F
// ...
}
Run Code Online (Sandbox Code Playgroud)
在任何一种情况下,F都是要传递给测试的fixture参数的类型,哪个套件子类将具体化.下面是一个具体测试套件的示例,需要使用类型参数方法将StringBuilder传递到每个测试中:
// Type parameter version
class MySuite extends FixtureSuite[StringBuilder] {
// ...
}
Run Code Online (Sandbox Code Playgroud)
这是一个具体测试套件的示例,需要使用抽象类型成员方法将StringBuilder传递到每个测试中:
// Type member version
class MySuite extends FixtureSuite {
type F = StringBuilder
// ...
}
Run Code Online (Sandbox Code Playgroud)
例如,如果要将三个不同的fixture对象传递给测试,您将能够这样做,但是您需要指定三种类型,每个参数一个.因此选择了类型参数方法,您的套件类可能最终看起来像这样:
// Type parameter version
class MySuite extends FixtureSuite3[StringBuilder, ListBuffer, Stack] with MyHandyFixture {
// ...
}
Run Code Online (Sandbox Code Playgroud)
而使用类型成员方法,它将如下所示:
// Type member version
class MySuite extends FixtureSuite3 with MyHandyFixture {
// ...
}
Run Code Online (Sandbox Code Playgroud)
因此,这显示了实现大型模块化抽象的两个目标.更多关于这个话题可以读这对伸缩性组件传奇纸