在派生类中重写方法时“对重载定义的模糊引用”

时间:2014-08-09 13:10:42

标签: scala compiler-errors override 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
                                    ^

您能否解释为什么D出现汇编错误以及为什么C无效?

提前致谢!

2 个答案:

答案 0 :(得分:0)

我认为编译器对无参数方法继承感到困惑,虽然我无法解释为什么说真的,快速解决方案应该可行:

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

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

为什么这种情况对我来说是模糊不清的,也许有人知道scala编译器如何看待无参数方法继承。

同时阅读,特别是Programming in Scala

  

这种无参数的方法在Scala中很常见。相比之下,使用空括号定义的方法(例如def height():Int)称为empty-paren方法。建议的约定是在没有参数时使用无参数方法,并且该方法仅通过读取包含对象的字段来访问可变状态(特别是,它不会改变可变状态)。   该约定支持统一访问原则1,该原则表明客户端代码不应受到将属性实现为字段或方法的决定的影响。例如,我们可以选择将宽度和高度实现为字段而不是方法,只需将每个定义中的def更改为val:

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

从客户的角度来看,这两对定义完全相同。唯一的区别是字段访问可能比方法调用稍快,因为字段值是在初始化类时预先计算的,而不是在每次方法调用时计算。另一方面,字段在每个Element对象中需要额外的内存空间。因此,它取决于类的使用情况,是否将属性更好地表示为字段或方法,并且该使用情况可能会随时间而变化。关键是当内部实现发生变化时,Element类的客户端不应受到影响。

答案 1 :(得分:-2)

为什么不提供这样的默认参数:

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

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 simpleBalanceOnDate = simpleAccount.balance(1)   // A
    val depositBalanceOnDate = depositAccount.balance(1) // B
    val simpleBalance = simpleAccount.balance()   // C
    val depositBalance = depositAccount.balance() // D