编辑:感谢 Derek 指出了错误消息的关键部分,我能够更多地提取关键部分,它似乎与存在类型有关。如果我确实正确理解了语言引用中的§3.2.10 对值的存在量化,那么 val m: Map[x.type#S, x.type#S] forSome { val x: T }
是 val m: Map[t#S, t#S] forSome { type t <: T with Singleton }
的简写。但在下面的代码中,它们的行为确实有所不同。
trait Type {
type S
}
class Concrete extends Type {
type S = Double
}
trait BaseWorks {
type T <: Type
val m: t#S forSome { type t <: T with Singleton }
}
class Works extends BaseWorks {
override type T = Concrete
override val m = 0.0
}
trait BaseError {
type T <: Type
val m: x.type#S forSome { val x: T }
}
class Error extends BaseError {
override type T = Concrete
override val m = 0.0
}
精炼BaseWorks
工作,同时精炼BaseError
导致错误error: overriding value m in trait BaseError of type Error.this.x.S forSome { val x: => Error.this.T }; value m has incompatible type
。我是否误解了§3.2.10?
原始文章:在下面的 Scala 代码片段中,编译器 (2.9.0.1) 生成一个错误,指出该方法 f2
覆盖 Derived
中的任何内容.
abstract trait Type {
type T1
type T2
type P = (T1, T2)
}
class ConcreteType extends Type {
type T1 = Double
type T2 = Double
}
abstract class Base {
type T <: Type
type TP = T#P
def f1(v: TP): TP
def f2(v: T#P): T#P
def f3(v: T#P): T#P
}
class Derived extends Base {
override type T = ConcreteType
override def f1(v: TP): TP = v
override def f2(v: T#P): T#P = v
override def f3(v: TP): TP = v
}
另一方面,重写函数f3
与代码中显示的完全相同的签名。我希望这两个函数的行为方式相同。为什么情况并非如此?
最佳答案
(仅供引用,我使用的是 2.9.0.1)
我无法在规范中找到此问题的原因,但您收到的错误消息至少清楚地表明了最终原因。这是关键部分:
(Note that (_5.T1, _5.T2) forSome { val _5: Base.this.T }
does not match
(_16.T1, _16.T2) forSome { val _16: Base#T }
Base.this.T
不等于 Base#T
。前者是基于实例 this
的路径相关类型,而后者是不基于实例的类型投影。
这似乎是由于类型解析的顺序造成的。 TP
根据 Base
的计算进行解析,而 T#P
则根据 Derived
的计算进行解析>.
如果有人可以指出规范中可以正确解释这一点的位置,我很乐意阅读它。
关于scala - 使用路径相关类型参数覆盖函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7025553/