为什么scalac不相信方法不适合所需的类型签名?
为什么不编译此文件?为什么scalac不相信方法不适合所需的类型签名?,scala,types,Scala,Types,为什么不编译此文件? 给出的错误是类SomeElement需要是抽象的,因为[T scala.util.Try[T]类型的trait元素中的方法eval没有定义 我无法理解为什么在SomeElement上定义的方法eval不满足类型约束 据我所知,eval应该返回包装在Try中的内容,其中包含类型的子类。 Try的类型参数是协变的。在SomeElement中执行eval会返回一个NumberLike,以及NumberLike子类Typed。那么出了什么问题 import scala.util.T
给出的错误是
类SomeElement需要是抽象的,因为[T scala.util.Try[T]类型的trait元素中的方法eval没有定义
我无法理解为什么在SomeElement上定义的方法eval
不满足类型约束
据我所知,eval
应该返回包装在Try
中的内容,其中包含类型的子类。
Try的类型参数是协变的。在SomeElement
中执行eval
会返回一个NumberLike
,以及NumberLike
子类Typed
。那么出了什么问题
import scala.util.Try
trait Element {
def eval[T <: Typed]: Try[T]
}
trait Typed
case class NumberLike(n: Long) extends Typed
case class SomeElement(n: Long) extends Element {
def eval = Try {
NumberLike(n)
}
}
object app extends Application {
println (SomeElement(5).eval)
}
将SomeElement的定义更改为上述内容,可以得到:
found : <empty>.NumberLike
required: NumberLike(in method eval)
NumberLike(n)
找到:.NumberLike
必填项:数字类(在方法评估中)
类数字(n)
编辑我真的很想知道为什么这不能编译。解决这个问题的方法很有用,但我真的想知道这里发生了什么。类型参数
t
是在函数上定义的,而不是在封闭的类型元素上定义的,它不能通过继承“擦除”,必须保持在重写函数()上
将类型参数移动到元素
定义,使其工作如下
trait-Element[T既然有人给出了解决方案,我想解释一下原因
在java中,类似这样的内容是非法的:
class A {
<T> T f() {return null;}
Object f() {return null;}
}
主要区别在于:scala处理两个名称相同且参数列表不同的方法,如果其中一个有类型参数,而另一个没有(我认为scala方法的签名包括类型参数,如果我错了请更正:))
因此,在您的情况下,您不能用普通方法覆盖带有类型参数的方法。(它们有不同的签名)
我不确定哪一个更好,我个人更喜欢scala规则:)我现在不能写一个完整的答案,但肯定的是,没有它,你不能用类型参数逐个函数重写/实现poly函数;所以你必须编写smth,比如def eval[t:NumberLike]=…
为什么抽象特征
?有什么意义吗?对我来说特征
或密封特征
就足够了。抽象实际上对特征没有任何作用,所以我想没有。这并不是说它改变了任何东西。@MrBones hm,现在没有编译器,认为有可能生成依赖类型:特征元素{type T这意味着所有扩展元素的东西都必须为元素提供一个类型参数。我更喜欢第二个。我认为它应该准备好T,这不是解决办法,编译器没有其他方法可以检查子类型中T
的类型安全性foo
的类型参数T
与A
的类型参数T
不同,除非它得到统一(class A[T]{def foo:T=?}
|class A{type T;def foo:T=?}
)。可以添加指向“匹配成员”的链接并删除“For me”。
class A {
<T> T f() {return null;}
Object f() {return null;}
}
class A {
def f[T](): T = ???
def f(): Any = ???
}