scala - 在派生类中覆盖方法时“对重载定义的引用不明确”

标签 scala compiler-errors overriding overloading

我有以下代码:

import com.github.nscala_time.time.Imports._

class Account {
    def balance(date: DateTime): Double = {
        /* some logic that calculates balance on given date */
        val calculatedBalance = 42
        calculatedBalance
    }

    def balance: Double = balance(DateTime.now)
}

class Deposit(val interestRate: Double) extends Account {
    override def balance(date: DateTime): Double = {
        /* some logic that calculates balance for deposit account */
        val calculatedBalance = 100 * interestRate;
        calculatedBalance
    }
}

我尝试按以下方式使用这些类:

val simpleAccount = new Account
val depositAccount = new Deposit(0.1)

val simpleBalanceOnDate = simpleAccount.balance(DateTime.now + 1.month)   // A
val depositBalanceOnDate = depositAccount.balance(DateTime.now + 1.month) // B
val simpleBalance = simpleAccount.balance   // C
val depositBalance = depositAccount.balance // D

案例 ABC 编译没有任何错误,但是对于行 D 我看到错误信息:

Error:(28, 38) ambiguous reference to overloaded definition,
both method balance in class Deposit of type (date: com.github.nscala_time.time.Imports.DateTime)Double
and  method balance in class Account of type => Double
match expected type ?
val depositBalance = depositAccount.balance
                                    ^

能否解释一下为什么case D有编译错误,而case C没有?

提前致谢!

最佳答案

我想编译器对无参数方法继承感到困惑,虽然我无法老实解释为什么,为了快速解决这个问题应该可行:

class Account {
  { ... }
  def balance(): Double = balance(DateTime.now)
}

val depositAccount = new Deposit(0.1)
val depositBalance = depositAccount.balance()

我不清楚为什么会发生这种情况,也许其他人知道 scala 编译器如何看待无参数方法继承。

还四处阅读,特别是 Programming in Scala :

Such parameterless methods are quite common in Scala. By contrast, methods defined with empty parentheses, such as def height(): Int, are called empty-paren methods. The recommended convention is to use a parameterless method whenever there are no parameters and the method accesses mutable state only by reading fields of the containing object (in particular, it does not change mutable state). This convention supports the uniform access principle,1 which says that client code should not be affected by a decision to implement an attribute as a field or method. For instance, we could have chosen to implement width and height as fields instead of methods, simply by changing the def in each definition to a val:

abstract class Element {
  def contents: Array[String]
  val height = contents.length
  val width = 
    if (height == 0) 0 else contents(0).length
}

The two pairs of definitions are completely equivalent from a client's point of view. The only difference is that field accesses might be slightly faster than method invocations, because the field values are pre-computed when the class is initialized, instead of being computed on each method call. On the other hand, the fields require extra memory space in each Element object. So it depends on the usage profile of a class whether an attribute is better represented as a field or method, and that usage profile might change over time. The point is that clients of the Element class should not be affected when its internal implementation changes.

关于scala - 在派生类中覆盖方法时“对重载定义的引用不明确”,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25218921/

相关文章:

java - 使用奇怪的泛型覆盖 java 方法中的错误

scala - 如何正确使用 MonadError?

scala - 当未明确给出返回类型时,为什么可以用返回 String 的方法覆盖返回 Unit 的方法?

variables - 为什么用变量名替换其值导致 “' xxx'应该被声明为“错误”?

Julia:重写方法以添加功能

C# 类 Java 类的内联扩展?

Scala 类变量名隐藏方法参数名

hibernate - 如何从 Play 2.0 中排除 Bean?

sorting - "nonL value in assignment "错误 C++对链表进行排序

Objective-c:现在允许我创建一个类的实例