我只是试图了解Scala的类型系统.我偶然发现了一个看起来像这样的代码:
trait A extends Something {
type X <: XLike
trait XLike { this: X =>
....
....
}
}
Run Code Online (Sandbox Code Playgroud)
这意味着什么?在哪种情况下我想要像这样编码?我知道我是嵌套类型,但嵌套类型的优点是什么,并使用它来引用嵌套类型?
这个A#XLike特性不能在任何地方混合A:
val a = new A {}; import a._
scala> class KK extends XLike
<console>:21: error: illegal inheritance;
self-type KK does not conform to a.XLike's selftype a.X
class KK extends XLike
^
Run Code Online (Sandbox Code Playgroud)
它可以在As实现中混合使用:
trait B extends A {
type X = XImpl
trait XImpl extends XLike { this: X => }
}
val b = new B {}; import b._
scala> class KK extends XImpl
defined class KK
Run Code Online (Sandbox Code Playgroud)
甚至:
trait B extends A {type X = XLike}
val b = new B {}; import b._
scala> class KK extends XLike
defined class KK
Run Code Online (Sandbox Code Playgroud)
因此,它允许您选择哪种特性是混合的:
trait B extends A {
type X = XImpl1
trait XImpl1 extends XLike { this: X => }
trait XImpl2 extends XLike { this: X => }
}
val b = new B {}; import b._
scala> class ZZ extends XImpl1
defined class ZZ
scala> class ZZ extends XImpl2
<console>:40: error: illegal inheritance;
self-type ZZ does not conform to b.XImpl2's selftype b.XImpl2 with b.X
class ZZ extends XImpl2
^
scala> class ZZ extends XImpl1 with XImpl2 // XImpl2 still can be mixed but only if XImpl1 present in linearization
defined class ZZ
Run Code Online (Sandbox Code Playgroud)
甚至几个:
trait A {
type X1 <: XLike
type X2 <: XLike
trait XLike { this: X1 with X2 => }
}
trait B extends A {
type X1 = XImpl1
type X2 = XImpl2
trait XImpl1 extends XLike { this: X1 with X2 => }
trait XImpl2 extends XLike { this: X1 with X2 => }
trait XImpl3 extends XLike { this: X1 with X2 => }
}
Run Code Online (Sandbox Code Playgroud)
在实践中,X1并X2可能有一些显著的作用.例如,如果你做了resposibilty链(可堆叠的特征) - 你可以按任何顺序混合许多特征(而不是所有特征 - 可能都有特征组),所以有能力指定一个或者几个强制处理程序(只是为了不忘记它们),如:
val a = new Logic with Hanler with Group0
trait Group0 extends MandatoryHandler1 with Group1 with H2
trait Group1 extends H3 with H4 with MandatoryHandler2
trait Group2 extends H2 with H5
Run Code Online (Sandbox Code Playgroud)
如果你改变Group0对Group2你可能会失去你的MandatoryHandler2(也可能是一些记者举例).
另外一个:图书馆开发人员可能会提供许多特征,以简洁的单一资产/接口隔离原则,但其中一些应该总是由玩这个乐高的用户混合在一起.
所以这里是经典的OOP-composition over aggregation方式(需要实例):
abstract class B {
val helper1: H1 //mandatory, exactly H1, not some H
val helper2: H2
}
class C extends B {
val helper1 = new H1 //mandatory, exactly H1, not some H
val helper2 = new H2
}
class H1 extends H {...}
class H2 extends H {...}
Run Code Online (Sandbox Code Playgroud)
vs 混合方式:
trait B extends A {
type helper1 = H1
type helper2 = H2
trait H1 extends H // no abstract members here just mix-in
trait H2 extends H
}
trait C extends H1 with H2
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
370 次 |
| 最近记录: |