【问题标题】:Scala: method\operator overloadingScala:方法\运算符重载
【发布时间】:2010-12-31 18:22:12
【问题描述】:

以下示例来自《Scala 编程》一书。给定一个“Rational”类和以下方法定义:

def add(that: Rational): Rational =
    new Rational(
        this.numer * that.denom + that.numer * this.denom,
        this.denom * that.denom
    )

我可以使用带有 Int 参数的便捷版本成功地重载 add 方法,并且使用上面的定义

def add(that: Int): Rational =
    add(new Rational(that, 1))

目前没有问题。

现在,如果我将方法名称更改为运算符样式名称:

def +(that: Rational): Rational =
    new Rational(
        this.numer * that.denom + that.numer * this.denom,
        this.denom * that.denom
    )

像这样重载:

def +(that: Int): Rational =
    +(new Rational(that, 1))

我得到以下编译错误:

(fragment of Rational.scala):19: error: value unary_+ is not a member of this.Rational
+(new Rational(that, 1))
 ^

为什么编译器要寻找 + 方法的一元版本?

【问题讨论】:

    标签: scala


    【解决方案1】:

    在 Scala 中,+x-x~x!x 类型的任何构造都将转换为方法调用 x.unary_+ 等。这部分是为了允许具有 @ 的类 Java 语法987654326@ 作为布尔值b 的否定,或-x 作为数字x 的否定。

    因此,代码sn -p +(new Rational(that, 1))被翻译成(new Rational(that,1)).unary_+,由于Rational没有这个方法,所以会出现编译错误。仅当您的函数被称为 +-~! 时,您才会收到此错误,因为这些是 Scala 允许作为一元运算符的唯一字符。例如,如果你调用你的函数@+,代码编译得很好。

    不过,我建议将重写的 add 函数编写为:

    def +(that: Int): Rational =
      this + (new Rational(that, 1))
    

    这段代码更好地显示了你的函数的意图——你添加了一个新的Rational,该Rational由一个整数作为分子和1作为分母构造到this。这种写法被翻译成this.+(new Rational(that, 1)),这就是你想要的——在this上调用+函数。

    请注意,您可以使用中缀表示法,但调用函数。例如,如果您将名称改回add,您仍然可以将定义保留为:

    def add(that: Int): Rational =
      this add (new Rational(that, 1))
    

    【讨论】:

      【解决方案2】:

      如果你用明确的this 调用+,它应该可以工作

      def +(that: Int): Rational = this.+(new Rational(that, 1))
      

      Scala 允许定义可以在前缀运算符表示法中使用的一元运算符。例如,您可以使用+ 作为前缀运算符来实现相同的目的:

      def unary_+: Rational = this.+(new Rational(that, 1))
      val a = new Rational(3,2)
      val b = +a
      

      如果您的示例中没有明确的this,编译器会认为您使用的是未定义的一元运算符+

      【讨论】:

        【解决方案3】:

        你还没有指定二元 + 运算符,你已经指定了一元 + 运算符。

        所以而不是:

        def +(that: Int): Rational =
          +(new Rational(that, 1))
        

        你需要这样写:

        def +(that: Int): Rational =
          this +(new Rational(that, 1))
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-10-19
          • 2015-08-22
          • 2019-03-29
          • 1970-01-01
          相关资源
          最近更新 更多