Я знаю, что невозможно перегрузить методы, которые отличаются только типом возврата. Но мне интересно, есть ли какие-нибудь умные стратегии, чтобы эффективно справиться с этой ситуацией:
trait Reader[A] { def read(in: java.io.DataInput): A }
trait B; trait C
def doSomethingB()(implicit r: Reader[B]) = ()
def doSomethingC()(implicit r: Reader[C]) = ()
trait MultiReader extends Reader[B] with Reader[C] { // not possible
implicit me = this
doSomethingB()
doSomethingC()
}
Под умным и эффективным я имею в виду, что я хотел бы избежать беспорядка и ненужных внутренних поколений, подобных этому:
trait MultiReader {
implicit object RB extends Reader[B] { ... }
implicit object RC extends Reader[C] { ... }
doSomethingB()
doSomethingC()
}
EDIT
Вот частичное решение. В последние дни я перечитывал эту суть Майлза Сабина, которая выглядела очень вдохновляющей. Поэтому я могу сделать следующее:
type Tagged[U] = { type Tag = U }
type @@[T, U] = T with Tagged[U]
trait Reader[A] { def read(in: java.io.DataInput @@ A): A }
И тогда это работает:
trait MultiReader {
def read(in: java.io.DataInput @@ B): B
def read(in: java.io.DataInput @@ C): C
}
Но наследство все еще несколько нарушено:
trait MultiReader extends Reader[B] with Reader[C]
(не работает с "self-type MultiReader does not conform to Reader[B]'s selftype Reader[B]"
).