【问题标题】:Declare self-type of a child trait in a parent trait in scala在scala的父特征中声明子特征的自我类型
【发布时间】:2016-01-20 06:10:27
【问题描述】:

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

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

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

我正在尝试将 self-type 声明抽象为一个父 trait,这样这些特征中的每一个都不必定义 self-type。我尝试了以下方法。

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 中有什么方法可以在父 trait 中强制实现子特征的自我类型?

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

我想要实现的是,我想省略为 BookDbModuleAuthorDbModule 设置自我类型的必要性,方法是扩展(或任何其他 scala 功能)父特征 DbModule 同时具有自我类型987654329@.

所以,基本上,我正在寻找一种方法,通过在父 DbModule 中声明 self-type 而不是在那些带有 DbConfig 的类中扩展子特征(BookDbModuleAuthorDbModule)儿童特质。

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

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

谢谢!

【问题讨论】:

  • 请说明您要达到的目标。这些消息(至少对我而言)确实说它们“强制执行自我类型的特征”。
  • 嗨@RobStarling,我已经更新了我的问题。请看一下。谢谢!
  • 感谢更新,更清楚了
  • 啊!知道了。抱歉,但我认为答案是“不”。

标签: scala inheritance traits self-type


【解决方案1】:

看看这个:

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

DbModule 需要 DbConfig 实现:

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

BookDbModuleDbModule 类型,仍然需要 DbConfig 实现:

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

BookDbModuleBookDbModule 类型,需要直接实现DbConfig

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

BookDbModuleBookDbModule 类型,需要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

【讨论】:

  • 您好,感谢您的回答。这个问题似乎有点令人困惑(更新)。这个错误是有道理的。我想做的是省略在extends DbModule之后写self: DbConfig =&gt;的必要性。
【解决方案2】:

答案是否定的。这不可能。事实上,你所说的与自我打字的目的背道而驰。

trait DbModule {
  self: DbConfig =>
}

trait BookDbModule extends DbModule {
}

在你的例子中(总结在这里),DbModule 说我的孩子必须以某种方式提供DbConfig 中定义的功能。但是 trait BookDbModule 无法显示,除非它扩展 DbConfig 或明确地自行键入它。这与你想要的背道而驰......

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-06-09
    • 1970-01-01
    • 2015-05-26
    • 2018-03-21
    • 2019-05-11
    • 1970-01-01
    • 2016-10-20
    • 2011-05-14
    相关资源
    最近更新 更多