scala – 抽象类型与类型参数
抽象类型在什么情况下优于类型参数?
解决方法
要添加到我的
previous answer on Abstract type vs. parameters,你也有
JESSE EICHAR’s recent blog post(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 } 在C2情况下,参数为“埋”(作为内部抽象类型)。 而通用类型,明确地提到了参数,帮助其他表达式知道他们应该使用什么类型 所以(C1:参数): //compiles def p(c:C1[Int]) = c.doit(c.get) 它编译,但是您明确公开您要使用的“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) ^ 它不编译,因为p2定义中没有提到’A’,所以doit在编译类型中不知道应该返回什么。 当使用抽象类型并希望避免对接口的任何“类型泄漏”(即,想要公开“A”实际上是什么)时,可以指定非常通用的类型作为p2的返回值: // compiles because the internals of C2 does not leak out def p(c:C2):Unit = c.doit(c.get) 或者您可以直接在doit函数中“修复”该类型 最后(retronym的评论),您可以通过细化C2抽象参数明确指定A: scala> def p2(c:C2 { type A = Int }): Int = c.doit(c.get) p2: (c: C2{type A = Int})Int 或者通过添加一个类型参数(并用它来提炼C2抽象类型!) scala> def p2[X](c:C2 { type A = X }): X = c.doit(c.get) p2: [X](c: C2{type A = X})X 所以推荐抽象: >当您想从客户端代码中隐藏类型成员的确切定义时,请使用像C2中的抽象类型(但要谨慎使用C2定义函数) 对于需要简单类型实例化的其余部分,请使用参数。 retronym补充说: 主要的区别是 >方差:C2只能在A中不变, (如illustrating here: 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(...) } ) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |