Scala: method\operator overloading
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
)
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))
No problems so far.
Now, if I change the method name to an operator style name:
def +(that: Rational): Rational =
new Rational(
开发者_如何学Go this.numer * that.denom + that.numer * this.denom,
this.denom * that.denom
)
And overload like so:
def +(that: Int): Rational =
+(new Rational(that, 1))
I get the following compile error:
(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?
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
.
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.
Though, I would suggest writing the overridden add function as:
def +(that: Int): Rational =
this + (new Rational(that, 1))
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
.
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))
If you call +
with explicit this
, it should work
def +(that: Int): Rational = this.+(new Rational(that, 1))
Scala allows to define unary operators that can be used in prefix operator notation. For example you can use +
as a prefix operator to achieve the same:
def unary_+: Rational = this.+(new Rational(that, 1))
val a = new Rational(3,2)
val b = +a
Without explicit this
in your example, the compiler thinks that you are using unary operator +
which is not defined.
You haven't specified the binary + operator, you've specified the unary + operator.
So instead of:
def +(that: Int): Rational =
+(new Rational(that, 1))
You need to write this:
def +(that: Int): Rational =
this +(new Rational(that, 1))
精彩评论