【问题标题】:Scala - inferred as wrong type, leading to type mismatch?Scala - 推断为错误类型,导致类型不匹配?
【发布时间】:2015-04-30 15:19:57
【问题描述】:

在 Scala 2.11.5 中,编译这个

object Tryout {
  trait A {
    def method(a: Int): Boolean
  }

  abstract class B extends A {
    def method(a: Int) = ???
  }

  new B {
    override def method(a: Int) = true  // type mismatch here
  }
}

在“真”处产生“类型不匹配:找到布尔值,不需要任何内容​​”。如果我用 true 或 false 替换 ???,它会编译。如果我在抽象类中指定“方法”的结果类型,它也会编译。

这不是什么大问题。但是我很好奇是否有人可以解释为什么 ??? 没有被正确推断为布尔值?

【问题讨论】:

  • 在抽象类 B 中将其更改为 def method(a: Int): Boolean = ???
  • 这实际上是一个已知的错误。如果我能找到票,我会链接它。我相信它会在 2.12 中修复。
  • @wheaties 你确定这是一个错误吗?在我看来,编译器会推断出最具体的类型(Nothing 是 Boolean 的子类型),这似乎是一致的。
  • 为什么你认为它是一个错误......?看起来一致...
  • 因为你覆盖了界面中给出的类型

标签: scala inheritance types


【解决方案1】:

Scala 允许您在子类中使继承方法的返回类型更具限制性。

abstract class A {
    def foo: Any
}

abstract class B {
    def foo: Int
}

new B {
    def foo = 1
}

所以当你在B 中声明def method(a: Int) = ??? 时,??? 被推断为Nothing,因为 scala 编译器不知道你想要Boolean 还是Nothing。这就是为什么显式声明返回类型总是一个好主意的原因之一。

【讨论】:

    【解决方案2】:

    def method(a: Int) = ??? 的返回类型实际上是Nothing

    scala> def method(a: Int) = ???
    method: (a: Int)Nothing
    

    现在,B 类中的 method 将覆盖父 trait 中的 method。你应该像这样定义你的 claas B,

    abstract class B extends A {
      // def method is provided by trait A
    }
    

    abstract class B extends A {
      // def method with full signature
      override def method(a: Int): Boolean = ???
    }
    

    【讨论】:

      猜你喜欢
      • 2011-04-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-16
      • 1970-01-01
      • 2012-09-02
      • 1970-01-01
      • 2015-12-31
      相关资源
      最近更新 更多