2016-01-20 2 views
2

У меня есть некоторые свойства scala с одинаковым самоналожением, объявленным следующим образом.Объявить самостоятельный тип дочернего признака в родительском признаке в 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 для принудительного использования признаков типа ребенка в родительском признаке?

Обновление: Похоже, вопрос немного запутан.

То, что я хочу добиться, я хочу, чтобы опустить необходимость установить самостоятельный тип для BookDbModule и AuthorDbModule путем расширения (или любого другого признака Scala) материнская черта DbModule, а имеют собственный тип DbConfig.

Так, в принципе, я ищу способ сделать детей черты (BookDbModule и AuthorDbModule) быть продлены только те классы с DbConfig объявляя собственного типа в родительских DbModule, но не в этих детских черт.

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

Пожалуйста, дайте мне знать, если он все еще запутан.

Спасибо!

+0

Просьба уточнить, чего вы пытаетесь достичь. Сообщения (для меня, по крайней мере) _do_ говорят, что они «навязывают себя типам признаков». –

+0

Привет @RobStarling, я обновил свой вопрос. Взгляни, пожалуйста. Благодаря! – TheKojuEffect

+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 
+0

Привет, спасибо за ваш ответ. Похоже, вопрос был немного запутанным (обновленным). Ошибка имеет смысл. То, что я хотел сделать, это опустить необходимость писать 'self: DbConfig =>' после 'extends DbModule'. – TheKojuEffect

0

Ответ отрицательный. Это невозможно. На самом деле то, что вы говорите, противоречит цели самонабора.

trait DbModule { 
    self: DbConfig => 
} 

trait BookDbModule extends DbModule { 
} 

В вашем примере (кратко здесь), DbModule говорит мои дети должны каким-то образом обеспечить функциональные возможности, определенные в DbConfig. Но черта BookDbModule не может показать, что, если она не расширяет DbConfig или явно ее не вводит. И это против того, что вы хотели ...

 Смежные вопросы

  • Нет связанных вопросов^_^