2013-03-24 4 views
3

Предположим, у меня есть класс типов:Тип класса и подклассов

trait ToString[T] { 
    def toString(t: T): String 
} 

И следующий сутенера:

implicit def ToStr[T: ToString](t: T) = new { 
    def toStr: String = implicitly[ToString[T]] toString t 
} 

Теперь давайте проверить это:

class A 
implicit object AToString extends ToString[A] { 
    def toString(a: A) = "A" 
} 
(new A).toStr // A 

Fine, так далеко. Но если я ввожу подкласс B из A:

class B extends A 
(new B).toStr // could not find implicit value for evidence parameter of type ToString[B] 

Так что я пробовал:

implicit def foo[X: ToString, Y <: X]: ToString[Y] = new ToString[Y] { 
    def toString(y: Y): String = implicitly[ToString[X]] toString y 
} 

Но потом я получил:

(new B).toStr // diverging implicit expansion for type ToString[...] 

Что я могу сделать, чтобы автоматически использовать класс типа для суперкласса, если существует класс типа type для подкласса?

ответ

8

Вы должны сделать параметр типа контрвариантных 'ToString':

trait ToString[-T] { 
    def toString(t: T): String 
} 

implicit def ToStr[T: ToString](t: T) = new { 
    def toStr: String = implicitly[ToString[T]] toString t 
} 

class A 
implicit object AToString extends ToString[A] { 
    def toString(a: A) = "A" 
} 

(new A).toStr // A 

class B extends A 
(new B).toStr // A 

Вы можете найти некоторую информацию о дисперсии в Скале здесь:

+0

Возможно объяснение будет в порядке? – Felix

+0

@Felix Я только что добавил ссылку на блог, введя введение в дисперсию типа. –

+0

Спасибо. конечно, контравариант. Глупый мне, хотя я недавно прочитал соответствующую главу в PinS. –