Scala递归类型
我只是想了解Scala的类型系统。我偶然发现了一个代码,看起来像这样:Scala递归类型,scala,types,Scala,Types,我只是想了解Scala的类型系统。我偶然发现了一个代码,看起来像这样: trait A extends Something { type X <: XLike trait XLike { this: X => .... .... } } trait A扩展了某些东西{ X型 .... .... } } 这意味着什么?在哪些情况下,我希望这样编码?我知道我是嵌套类型,但是像这样的嵌套类型并使用它来引用嵌套类型有什么好处呢?这个A#XLike特性不能在A
trait A extends Something {
type X <: XLike
trait XLike { this: X =>
....
....
}
}
trait A扩展了某些东西{
X型
....
....
}
}
这意味着什么?在哪些情况下,我希望这样编码?我知道我是嵌套类型,但是像这样的嵌套类型并使用它来引用嵌套类型有什么好处呢?这个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
^
甚至:
trait B extends A {type X = XLike}
val b = new B {}; import b._
scala> class KK extends XLike
defined class KK
因此,它允许您选择必须融入的特征:
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
如果您将Group0
更改为Group2
,您可能会失去MandatoryHandler2
(例如,可能是某个reporter)
另一个:库开发人员可能会提供许多简洁的特性,但其中一些特性应该始终由使用这款乐高的用户混合在一起
因此,这里是典型的过度聚合方式(需要实例):
vs方式:
可能的用例是什么?为什么我需要做这些戏剧性的事情?“我偶然发现了一个类似这样的代码”-这个怎么样。别担心,这里没有什么戏剧性的,因为代码非常简单——你只是说一个特征应该总是与另一个特征混合在一起——这只是额外的编译时检查。例如,当你做责任链时——你可能会混合9000多个特征,所以最好能够指定一个或多个强制处理程序,like
vala=带有Hanler和OtherHandlerList的新逻辑;trait OtherHandlerList将MandatoryHandler扩展为带有H2的H1
——这只是第一次想到它。@user3102968为答案添加了更多示例
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
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 => }
}
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
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 {...}
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