以下示例来自“Programming in Scala”一书 . 给定一个类'Rational'和以下方法定义:
def add(that: Rational): Rational =
new Rational(
this.numer * that.denom + that.numer * this.denom,
this.denom * that.denom
)
我可以使用带有Int参数的便捷版本和 makes use of the definition above 成功重载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))
^
为什么编译器要查找 +
方法的一元版本?
3 回答
在Scala中,
+x
,-x
,~x
和!x
类型的任何构造都转换为方法调用x.unary_+
等 . 这部分是为了允许类似Java的语法将!b
作为布尔b
的否定,或-x
作为否定号码x
.因此,代码段
+(new Rational(that, 1))
被转换为(new Rational(that,1)).unary_+
,而Rational
没有此方法,则会出现编译错误 . 只有当您的函数被调用+
,-
,~
或!
时,才会出现此错误,因为这些是Scala允许作为一元运算符的唯一字符 . 例如,如果您调用函数@+
,则代码编译得很好 .虽然,我建议将重写的add函数写为:
此代码更好地显示了函数的意图 - 添加一个由整数构成的新
Rational
作为分子,1
作为分母this
. 这种写法方式被翻译成this.+(new Rational(that, 1))
,这就是你想要的 - 在this
上调用+
函数 .请注意,您可以使用中缀表示法,但调用该函数 . 例如,如果将名称更改回
add
,仍可将定义保持为:如果您使用显式
this
调用+
,它应该可以工作Scala允许定义可用于前缀运算符表示法的一元运算符 . 例如,您可以使用
+
作为前缀运算符来实现相同的目的:如果在您的示例中没有显式的
this
,编译器会认为您正在使用未定义的一元运算符+
.您尚未指定二元运算符,您已指定了一元运算符 .
所以代替:
你需要写这个: