Scala 递归类型

标签 scala types

我只是想了解一下 Scala 的类型系统。我偶然发现了一个看起来像这样的代码:

trait A extends Something {
  type X <: XLike

  trait XLike { this: X =>
    ....
    ....
  }
}

这意味着什么?在什么情况下我想这样编码?我知道我在嵌套类型,但是像这样嵌套类型并使用它来引用嵌套类型有什么好处?

最佳答案

这个 A#XLike trait 不能在 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
                        ^

它可以混合在A的实现中:

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

甚至:

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

甚至几个:

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 => }
}

在实践中,X1X2 可能有一些重要的作用。例如,如果你做责任链(stackable traits) - 你可以以任何顺序混合许多特征(而不是所有特征 - 可能有一组特征),所以最好能够指定一个或几个强制处理程序(只是为了不要忘记它们),例如:

 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

如果您将 Group0 更改为 Group2,您可能会丢失您的 MandatoryHandler2(例如,它可能是一些记者)。

另一个:库开发人员可能会提供许多特性来使 Single Resposibilty / Interface Segregation 简洁明了。原则,但其中一些应始终由将玩此 LEGO 的用户混合(一起)。

所以这是经典OOP-composition过度聚合方式(需要实例):

 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 {...}    

对比mix-in方式:

 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 

关于Scala 递归类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30056817/

相关文章:

json - Scala和Elasticsearch的潜在性能问题

haskell - 解析存在类型的函数调用

typescript - 使用 typescript 的 enzyme 中 ReactWrapper 的确切类型

scala - 无法实例化路由器 [一致哈希池],在 akka/spray 中的 [/IO-DNS/inet-address] 错误中定义

scala - 我如何用微风通过双倍缩放矩阵

c - 如何处理 C 中的数据类型不匹配异常

php - PHP 中抽象类和特征的类型协变

c# - 从全名创建 C# 类型

scala - q"null"的类型是 Literal,因此对于返回类型 Expr[X] 无效

scala - 在spark中导入TSV文件