Wystąpiło to dziwne zachowanie po zmianie górnej granicy w implementacji, ale zapomniałem go zmienić w interfejsie. Myślę, że ostatnie oświadczenie nie powinno się kompilować, ale działa i zwraca nieoczekiwany rezultat.Dziwne zachowanie wnioskowania o typie w funkcji z górną granicą
trait SuperBase
trait Base extends SuperBase
class SuperBaseImpl extends SuperBase
trait Service {
def doWork[T <: Base : Manifest](body: T => Unit): String
def print[T <: Base : Manifest]: String
}
object ServiceImpl extends Service {
override def doWork[T <: SuperBase : Manifest](body: T => Unit): String =
print[T]
def print[T <: SuperBase : Manifest]: String =
manifest[T].runtimeClass.toString
}
val s: Service = ServiceImpl
// does not compile as expected
// s.print[SuperBaseImpl]
// returns "interface Base"
s.doWork { x: SuperBaseImpl =>() }
Edit
Jako @ som-snytt wspomniano o -Xprint:typer
opcji możemy zobaczyć, co kompilator faktycznie wywodzi:
s.doWork[Base with SuperBaseImpl]
To wyjaśnia, dlaczego kupujemy "interfejs podstawowy". Ale wciąż nie do końca rozumiem, jak i dlaczego w tym przypadku działa inferencja typów.
Dzięki, ale myślę, że łatwiej jest po prostu zdefiniować 'T' jawnie:' s.doWork [SuperBaseImpl] {x =>()} '. –