首页 文章

在scala中声明父特征中的子特征的自我类型

提问于
浏览
3

我有一些具有相同自我类型的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有没有办法在父母特质中强制实施自我类型的儿童特质?

Update: 看起来这个问题有点令人困惑 .

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

所以,基本上,我正在寻找一种方法,通过在父 DbModule 中声明自我类型而不是在那些子特征中,仅通过 DbConfig 扩展子类特征( BookDbModuleAuthorDbModule ) .

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

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

谢谢!

2 回答

  • 0

    看看这个:

    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 ,即"complete":

    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

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

    trait DbModule {
      self: DbConfig =>
    }
    
    trait BookDbModule extends DbModule {
    }
    

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

相关问题