【发布时间】:2018-03-15 21:05:17
【问题描述】:
我有以下简单的演示代码,它给了我类型不匹配的错误。 我很不明白为什么会发生这个错误。谁能告诉我如何解决这个错误。进一步解释或相关的学习资源将不胜感激。
object Application extends App {
private val foo = new Foo
private val holder = new FooTypeHolder
private val client = new Client(holder)
client.showElementType(foo)
}
class Foo
trait TypeHolder[T] {
type ElementType = T
}
class FooTypeHolder extends TypeHolder[Foo]
class Client[T <: TypeHolder[_]](val holder: T) {
def showElementType(t: T#ElementType): Unit = {
println("show element type " + t.toString)
println(t.getClass)
}
}
编译错误为:
Error:(10, 26) type mismatch;
found : Application.foo.type (with underlying type Foo)
required: _$1
client.showElementType(foo)
2018 年 3 月 15 日更新
就像 Andrey Tyukin 会对 TypeHolder 的用途感到好奇一样,它除了 T 之外什么都没有。我在这个特征上添加了一些功能。
代码如下。
object Application extends App {
private val foo = new Foo
private val holder = new FooTypeHolder
private val client = new Client(holder)
client.showElementType(foo)
}
class Foo
trait TypeHolder[T] {
type ElementType = T
def holderFun(): Unit = println(s"holder, type:${getClass}")
def elementFun(ele: ElementType): Unit = println(s"element, type:${getClass}")
}
class FooTypeHolder extends TypeHolder[Foo]
class Client[T <: TypeHolder[_]](val holder: T) {
def showElementType(t: T#ElementType): Unit = {
println("show element type " + t.toString)
holder.holderFun()
holder.elementFun(t)
}
}
编译错误如下:
Error:(10, 26) type mismatch;
found : o2.Application.foo.type (with underlying type o2.Foo)
required: _$1
client.showElementType(foo)
Error:(30, 23) type mismatch;
found : _$1
required: Client.this.holder.ElementType
(which expands to) _$1
holder.elementFun(t)
总的来说,我想知道的核心是:
当我通过 val client = new Client(holder) 实例化 client
而holder 的类型为:TypeHolder[Foo]
scala编译器是否可以推断hoder的ElementType是“Foo”?
非常感谢@Andrey 提供各种可行的解决方案。 我检查了你的代码sn -p 1~3,并仔细对比了我的代码,这让我现在更清楚了。不过我还有一些问题。
版本 3
这个版本的代码最接近我原来的邮政编码。唯一的区别是函数showElementType的类型限制
- 我的:
def showElementType(t: T#ElementType): Unit - 您的:
def showElementType(t: holder.ElementType): Unit
让我感到困惑的是,既然“(t: holder.ElementType)”有效,那么“(t: T#ElementType)”也应该有效吗?而实际上并非如此。为什么?
版本 2
这里的区别是type ElementType = T 的位置。我把它放在特征定义中,而你把它放在类型参数限制中。
- 我的:
trait TypeHolder[T] { type ElementType = T} - 您的:
class Client[T, H <: TypeHolder { type ElementType = T }]
我不明白为什么特征定义中的赋值语句不起作用。
版本 1
您使用两个类型参数T 和H 分别捕获Foo 和TypeHolder 的类型。它应该绝对有效。客户端的类型也对应Client[Foo, TypeHolder[Foo]]。我的问题是,是否可以定义客户端仅使用一种类型参数,例如Client[TypeHolder[Foo]]。换句话说,编译器是否有可能从TypeHolder[Foo] 推断出ElementType 是Foo?
谢谢。
【问题讨论】:
-
这看起来像一个
XY-problem,到目前为止,答案似乎不同,以至于人们可能会假设回答者试图随机猜测X-part。例如,我建议去掉TypeHolder,而@MarkoŠvaljek 建议不要使用Foo-typedfoo作为showElementType的参数。尽管所有这些解决方案建议都可以编译,但生成的程序的含义似乎大不相同。需要进一步澄清预期的X。
标签: scala