以下是 Programming Scala 中a chapter的观察结果。
在Scala中,我经常看到抽象特征模式:
trait Abstract {
type T
def transform(x: T): T
val initial: T
var current: T
}
class Concrete extends Abstract {
type T = String
def transform(x: String) = x + x
val initial = "hi"
var current = initial
}
为什么我会在参数化泛型上选择抽象特征模式?
trait Abstract[T] {
def transform(x: T): T
val initial: T
var current: T
}
class Concrete extends Abstract[String]{
def transform(x: String): x + x
val initial: "hi"
var current: initial
}
答案 0 :(得分:3)
这两种方法大多相同。我们可能更喜欢类型成员的一个原因是,方法可以使用依赖类型编写,而不必是通用的:
def doSomethingWith(a: Abstract): a.T = ...
可以说比
更具可读性def doSomethingWith[T](a: Abstract[T]): T = ...
至少在签名变得更复杂时(特别是如果我们正在进行类型级编程,使用Abstract
作为类型级函数)。
类型推断可能也有影响;我不确切地知道scala类型推断是如何工作的,但据我所知,没有办法部分指定函数的类型:
def functionWeWantToCall[U, V, W](a: Abstract[U], b: Abstract[V], c: Abstract[W])
functionWeWantToCall[String, _, _](x, y, z) //won't compile
def functionWeWantToCall(a: Abstract, b: Abstract, c: Abstract)
functionWeWantToCall(x: Abstract{type T = String}, y, z) //works
所以这就是我有时发现自己使用类型成员方法的原因。
当然,有些人(例如来自ML背景的人)只是发现类型成员方法更熟悉或可读。