在scala

时间:2016-01-20 06:10:27

标签: scala inheritance traits self-type

我有一些具有相同自我类型的scala特征,如下所示。

trait BookDbModule {
  self: DbConfig => // Abstract this to a parent trait
  /* ... */
}

trait AuthorDbModule {
  self: DbConfig => // Abstract this to a parent trait
  /* ... */
}

我试图将自我类型声明抽象为父特征,这样每个特征都不必定义自我类型。我尝试了以下内容。

trait DbModule {
  self: DbConfig =>
  // Some common DbModule methods
}

// !!! Illegal Inheritance, self-type BookDbModule does not conform to DbConfig
trait BookDbModule extends DbModule {
  // What needs to be used instead of extends?
  /* ... */
}

// !!! Illegal Inheritance, self-type AuthorDbModule does not conform to DbConfig
trait AuthorDbModule extends DbModule {
  // What needs to be used instead of extends?
  /* ... */
}

错误消息Illegal Inheritance对我有意义,因为BookDbModule未延伸DbConfig

Scala有没有办法在父母特质中强制实施自我类型的儿童特质?

更新 似乎问题有点令人困惑。

我想要实现的是,我想省略通过扩展(或任何其他scala功能)父特征BookDbModuleAuthorDbModuleDbModule设置自我类型的必要性有自我类型DbConfig

所以,基本上,我正在寻找一种方法,通过在父{BookDbModule中声明自我类型AuthorDbModule来扩展儿童特征(DbConfigDbModule) {1}}但不是那些儿童特质。

// This works but is there any way to omit necessity to write
// self: DbConfig =>
trait AuthorDbModule extends DbModule {
  self: DbConfig =>
  /* ... */
}

如果它仍然令人困惑,请告诉我。

谢谢!

2 个答案:

答案 0 :(得分:1)

看看这个:

scala> trait DbConfig { def f = 123 }
defined trait DbConfig
需要DbModule实施的

DbConfig

scala> trait DbModule { self: DbConfig => }
defined trait DbModule

BookDbModule属于DbModule类型,仍需要DbConfig实施:

scala> trait BookDbModule extends DbModule { self: DbConfig => }
defined trait BookDbModule
scala> new BookDbModule with DbConfig {}.f
res0: Int = 123

BookDbModule属于BookDbModule类型,需要直接执行DbConfig

scala> trait BookDbModule { self: DbConfig => }
defined trait BookDbModule
scala> new BookDbModule with DbConfig {}.f
res1: Int = 123

BookDbModule属于BookDbModule类型,需要DbModule实施,而这又要求DbConfig实施:

scala> trait BookDbModule { self: DbModule => }
defined trait BookDbModule

scala> new BookDbModule with DbConfig {}.f
<console>:14: error: illegal inheritance;
 self-type BookDbModule with DbConfig does not conform to BookDbModule's selftype BookDbModule with DbModule
       new BookDbModule with DbConfig {}.f
           ^

scala> new BookDbModule with DbConfig with DbModule {}.f
res3: Int = 123

您也可以使用继承:

trait BookDbModule extends DbModule with DbConfig
scala> new BookDbModule with DbConfig {}.f
res4: Int = 123

但是你不能以某种方式继承自我类型注释,所以你可以求助于继承,或者明确地使用自我类型注释。请注意,这种简化也是可能的:

scala> trait DbConfig { def f = 123 }
defined trait DbConfig

scala> trait DbModule { self: DbConfig => }
defined trait DbModule

scala> trait DbModuleService extends DbModule with DbConfig
defined trait DbModuleService

最接近您要找的内容,但必须使用“完整”的中间特征DbModuleService

scala> trait BookDbModule extends DbModuleService
defined trait BookDbModule

scala> new BookDbModule {}.f
res0: Int = 123

或者:

scala> trait DbConfig { def f = 123 }
defined trait DbConfig

scala> trait DbModule { self: DbConfig => }
defined trait DbModule

scala> trait DbModuleService extends DbModule with DbConfig
defined trait DbModuleService

scala> trait BookDbModule { self: DbModuleService => }
defined trait BookDbModule

scala> new BookDbModule with DbModuleService {}.f
res0: Int = 123

答案 1 :(得分:0)

答案是否定的。这不可能。事实上你所说的是违背自我打字的目的。

trait DbModule {
  self: DbConfig =>
}

trait BookDbModule extends DbModule {
}

在您的示例中(此处总结),DbModule表示我的孩子必须以某种方式提供DbConfig中定义的功能。但特征BookDbModule无法显示,除非它延伸DbConfig或明确自我输入。那是违背你想要的......