以下是我的原始代码的简化版本,使事情变得更简单(抱歉还是有点复杂):
trait BuilderBase
trait MessageBase {
type Builder <: BuilderBase
}
class SomeMessage extends MessageBase {
type Builder = SomeMessage.Builder
}
object SomeMessage {
class Builder extends BuilderBase
}
class Covariant[+T]
class NonCovariant[T]
def func[T <: MessageBase](value: Covariant[T]): Covariant[T#Builder] = null
val message: Covariant[SomeMessage] = null
val result: Covariant[SomeMessage.Builder] = func(message)
最后一行编译失败,出现错误
func(→ message ← here)
:type mismatch; found : Covariant[SomeMessage] required: Covariant[SomeMessage.type]
func肯定是取了MessageBase的子类T的Covariant的参数,需要的是Covariant[SomeMessage]而不是Covariant[SomeMessage.type],因为SomeMessage.type(伴生对象SomeMessage的类型)不符合MessageBase。
奇怪的是,如果没有类型注释,错误就会消失,比如,
val result = func(message)
,并且结果的类型与含义完全相同:Covariant[SomeMessage.Builder]。所以它只是因为正确的类型注释而失败。这是一个错误吗?另一个线索是,当所有协变都被非协变替换时,这不会发生。所以它可能以某种方式与协方差有关。任何建议或帮助将不胜感激。
我知道一些小的调整可以解决这个特定问题,例如简单地省略类型注释可能是其中之一。但是,如果我能获得更多关于编译器中真正发生的事情的线索,例如通过为其提供一些命令行选项,那将非常有帮助。
最佳答案
我也不知道原因,但为了给@AssafMendelson 的答案提供一个轻微的替代方案,以下也有效:
trait BuilderBase
trait MessageBase {
type Builder <: BuilderBase
}
class SomeMessage extends MessageBase {
type Builder = BuilderBase {}
}
class Covariant[+T]
class NonCovariant[T]
def func[T <: MessageBase](value: Covariant[T]): Covariant[T#Builder] = null
val message: Covariant[SomeMessage] = null
val result: Covariant[SomeMessage#Builder] = func(message)
所以基本上不是在伴随对象中定义类,只需在类中定义它
关于Scala:有问题的类型推断?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43524827/