为什么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 = ???
}