Scala:方法\运算符重载 [英] Scala: method\operator overloading

查看:46
本文介绍了Scala:方法\运算符重载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

The following example is from the book 'Programming in Scala'. Given a class 'Rational' and the following method definition:

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

我可以使用接受 Int 参数的便捷版本成功重载 add 方法,并且利用上面的定义:

I can successfully overload the add method with a convenience version that takes an Int argument, and makes use of the definition above:

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

目前没有问题.

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

Now, if I change the method name to an operator style name:

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))
 ^

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

Why is the compiler looking for a unary version of the + method?

推荐答案

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

In Scala, any construct of the type +x, -x, ~x and !x is transformed into a method call x.unary_+, etc. This is partially to allow Java-like syntax of having !b as the negation of the boolean b, or -x as the negation of the number x.

因此,代码片段 +(new Rational(that, 1)) 被翻译成 (new Rational(that,1)).unary_+,并作为Rational 没有这个方法,你会得到一个编译错误.仅当您的函数被调用 +-~! 时,您才会收到此错误,因为这些是Scala 只允许将字符用作一元运算符.例如,如果您调用函数 @+,则代码编译得很好.

Therefore, the code snippet +(new Rational(that, 1)) is translated into (new Rational(that,1)).unary_+, and as Rational doesn't have this method, you get a compile error. You will get this error only if your function is called +, -, ~ or ! as these are the only characters Scala allows as unary operators. For example, if you called your function @+, the code compiles just fine.

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

Though, I would suggest writing the overridden add function as:

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

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

This code shows the intent of your function better -- you add a new Rational constructed from an integer as a numerator and 1 as denominator to this. This way of writing gets translated into this.+(new Rational(that, 1)), which is what you want -- invoking the + function on this.

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

Note that you can use the infix notation however the function is called. For example, if you change the name back to add, you can still keep the definition as:

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

这篇关于Scala:方法\运算符重载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆