trait Thing {
type Out
def get: Out
}
case class Wrapper(t: Thing) extends Thing {
type Out = t.Out
override def get = t.get
}
def hey(t: Thing): t.Out = Wrapper(t).get
这给了我一个类型错误,虽然它显然是类型安全的。我想知道如何向编译器正确证明这是安全的,而不必进行演员表。
有什么想法吗?
答案 0 :(得分:5)
如果你真的,真的不想在Wrapper
上放置一个类型参数,那么你可以用一个不太健忘的apply
推出自己的假案例类:
trait Thing {
type Out
def get: Out
}
abstract class Wrapper(t: Thing) extends Thing
object Wrapper {
def apply(t: Thing): Wrapper { type Out = t.Out } =
new Wrapper(t) {
type Out = t.Out
def get: Out = t.get
}
}
def hey(t0: Thing): t0.Out = Wrapper(t0: Thing { type Out = t0.Out }).get
(在现实生活中,你也想要定义案例类给你的所有其他东西 - 有用的平等等。)
问题是,在定义案例类时自动生成的Wrapper.apply
只返回Wrapper
,这意味着编译器丢失了有关其Out
的所有静态信息}。如果您编写自己的apply
,则可以通过使返回类型为指定Out
的细化类型来保留该信息。
证明它有效:
scala> val myThing = new Thing {
| type Out = String
| def get = "foo"
| }
myThing: Thing{type Out = String} = $anon$1@5e265ba4
scala> hey(myThing)
res0: myThing.Out = foo
scala> val foo: String = hey(myThing)
foo: String = foo
因此,编译器能够一直跟踪Out
String
的事实。