Von*_*onC 19
要添加我之前关于抽象类型与参数的答案,您还有JESSE EICHAR最近的博客文章(2010年5月3日),突出了一些主要差异:
trait C1[A] {
def get : A
def doit(a:A):A
}
trait C2 {
type A
def get : A
def doit(a:A):A
}
Run Code Online (Sandbox Code Playgroud)
在C2
情况下,参数是"埋"(作为内部抽象类型).
(除了反义词之外,它实际上并没有被埋没,见下文)
而使用泛型类型时,会明确提及该参数,从而帮助其他表达式知道它们应该使用哪种类型
所以(C1:参数):
//compiles
def p(c:C1[Int]) = c.doit(c.get)
Run Code Online (Sandbox Code Playgroud)
它编译,但你明确暴露了A
你想要使用的' '类型.
并且(C2:抽象类型):
// doesn't compile
def p2(c:C2) = c.doit(c.get)
<console>:6: error: illegal dependent method type
def p2(c:C2) = c.doit(c.get)
^
Run Code Online (Sandbox Code Playgroud)
它不会编译因为' A
'在p2定义中从未被提及过,所以doit
在编译类型中不知道它应该返回什么.
当使用抽象类型并希望避免任何"类型泄漏"到接口时(即想要暴露A
实际上是什么),您可以指定一个非常通用的类型作为p2的返回:
// compiles because the internals of C2 does not leak out
def p(c:C2):Unit = c.doit(c.get)
Run Code Online (Sandbox Code Playgroud)
或者你可以直接在doit
函数中"修复"那个类型:
def doit(a:A):Int
而不是 def doit(a:A):A
,这意味着:
def p2(c:C2) = c.doit(c.get)
将编译(即使p2没有提到任何返回类型)
最后(返璞词的注释),你可以指定A
任何明确细化C2抽象的参数:
scala> def p2(c:C2 { type A = Int }): Int = c.doit(c.get)
p2: (c: C2{type A = Int})Int
Run Code Online (Sandbox Code Playgroud)
或者通过添加一个类型参数(并用它来改进C2抽象类型!)
scala> def p2[X](c:C2 { type A = X }): X = c.doit(c.get)
p2: [X](c: C2{type A = X})X
Run Code Online (Sandbox Code Playgroud)
建议如此抽象:
C2
(但要警惕使用函数的定义C2
)C2
,请使用抽象类型(带有有界类型的抽象)C2
通过traits 混合使用这些类型的定义时,使用抽象类型(A
当C2
你和你的类混合时你不需要处理它:你只混合使用C2
)对于需要简单类型实例化的其余部分,请使用参数.
(如果你知道不需要扩展,但你仍然需要处理几种类型:这就是参数类型的用途)
反语:
的主要区别是
C2
只能是不变的A
,(如下图所示:
trait T1 {
type t
val v: t
}
trait T2 extends T1 {
type t <: SomeType1
}
trait T3 extends T2 {
type t <: SomeType2 // where SomeType2 <: SomeType1
}
class C extends T3 {
type t = Concrete // where Concrete <: SomeType2
val v = new Concrete(...)
}
Run Code Online (Sandbox Code Playgroud)
)
归档时间: |
|
查看次数: |
3267 次 |
最近记录: |