Подтвердить что ты не робот

Больше Scala idiomatic: trait TraitA расширяет TraitB или признак TraitA {self: TraitB =>}

Помимо аспекта наследования, существует ли разница между следующими шаблонами классов:

1| trait TraitA extends TraitB

2| trait TraitA { self: TraitB => }

Я хотел бы разделить обязанности между TraitA и TraitB, но первая не может функционировать без последней.

Как бы вы выразили это намерение? Для меня решение [2] было бы более естественным. Однако я не хочу ставить бремя на разработчиков, смешивая их в том, что нужно смешивать в любом случае.

4b9b3361

Ответ 1

Мое предпочтение обычно [1], потому что, как вы говорите, разработчик не обременен смешением (подтип) TraitB. Возможно, [2] предпочтительнее, если по какой-то причине желательно не наследовать конкретные реализации в TraitB и заставлять разработчика делать выбор среди подтипов TraitB. Тем не менее, [1] так же гибко.

Я стараюсь использовать [2] только там, где это необходимо, например, когда тип не является известным классом или признаком,

// Here, Matrix cannot extend type parameter Repr
trait Matrix[+Repr <: Matrix[Repr]] { self: Repr =>
  ...
}

Update. Здесь еще одно небольшое отличие,

trait B
trait A { self: B => }
def g(ab: A): B = ab // Type mismatch: found A, required B

Немного раздражает необязательное ограничение, чтобы не использовать A как B, даже если этот тип включен.