以下示例来自"Programming in Scala"一书.给定一个类'Rational'和以下方法定义:
def add(that: Rational): Rational =
new Rational(
this.numer * that.denom + that.numer * this.denom,
this.denom * that.denom
)
Run Code Online (Sandbox Code Playgroud)
我可以使用带有Int参数的便捷版本成功地重载add方法,并使用上面的定义:
def add(that: Int): Rational =
add(new Rational(that, 1))
Run Code Online (Sandbox Code Playgroud)
到目前为止没问题.
现在,如果我将方法名称更改为运算符样式名称:
def +(that: Rational): Rational =
new Rational(
this.numer * that.denom + that.numer * this.denom,
this.denom * that.denom
)
Run Code Online (Sandbox Code Playgroud)
像这样过载:
def +(that: Int): Rational =
+(new Rational(that, 1))
Run Code Online (Sandbox Code Playgroud)
我得到以下编译错误:
(fragment of Rational.scala):19: error: value unary_+ is not a member of this.Rational
+(new Rational(that, 1))
^
Run Code Online (Sandbox Code Playgroud)
为什么编译器要查找该+方法的一元版本?
Fla*_*gan 51
在Scala中,所述类型的任何构建体+x,-x,~x和!x被变换成一个方法调用x.unary_+,等等,这是部分地以允许具有的类似Java的语法!b作为布尔的否定b,或-x作为数的否定x.
因此,代码片段+(new Rational(that, 1))被翻译成(new Rational(that,1)).unary_+,并且由于Rational没有此方法,您会收到编译错误.只有在调用函数时+,才会出现此错误-,~或者!这些是Scala允许作为一元运算符的唯一字符.例如,如果您调用了函数@+,则代码编译得很好.
虽然,我建议将重写的add函数写为:
def +(that: Int): Rational =
this + (new Rational(that, 1))
Run Code Online (Sandbox Code Playgroud)
此代码更好地显示了函数的意图 - 添加一个Rational由整数构造的新分子1作为分子和分母this.这种写作方式被翻译成了this.+(new Rational(that, 1))你想要的东西 - 调用+函数this.
请注意,您可以使用中缀表示法,但调用该函数.例如,如果将名称更改回add,则仍可将定义保持为:
def add(that: Int): Rational =
this add (new Rational(that, 1))
Run Code Online (Sandbox Code Playgroud)
如果你+用显式调用this,它应该工作
def +(that: Int): Rational = this.+(new Rational(that, 1))
Run Code Online (Sandbox Code Playgroud)
Scala允许定义可用于前缀运算符表示法的一元运算符.例如,您可以使用+前缀运算符来实现相同的目的:
def unary_+: Rational = this.+(new Rational(that, 1))
val a = new Rational(3,2)
val b = +a
Run Code Online (Sandbox Code Playgroud)
this在您的示例中没有显式,编译器认为您使用的+是未定义的一元运算符.
| 归档时间: |
|
| 查看次数: |
32625 次 |
| 最近记录: |