(Translation) Operator overloading in Scala

image

One can argue for a long time whether the ability to overload operators is a strong or weak side of a particular language. But the fact remains - in Scala there is such an opportunity. So why not use it?

The article is intended mainly for beginner Scala developers.

Operator Overload


So what exactly is operator overloading?
In general, operators are the familiar “+”, “-”, “*”, “!” and many others. Moreover, sometimes the same operator can behave differently depending on what it operates with (for example, + as taking the sum of integers and + as the string concatenation operation). The idea of ​​operator overloading is simple - if the operator’s behavior changes depending on the class of objects with which it works, then why not define new behavior for it specifically for your class?

Wait a minute! But they told me that overloading operators is evil!

Overloading operators is a rather controversial topic. It is often said that this is the cause of many abuses, and this feature was slandered in C ++ so that the creators of the Java language deliberately abandoned it (with the exception of the + operator to concatenate strings).

I have a slightly different opinion. If you approach the overload of operators with due responsibility, then you can extract significant practical benefits. Let me give you an example: many objects can be added together or added up, so why not just use the "+" operator?

Suppose you wrote a class for complex numbers, and you want complex numbers to be added. Isn't it more pleasant to write the following code:

Complex result = complex1 + complex2;
... than ...
Complex result = complex1.add(complex2);

The first line looks more natural, doesn't it?

So, does Scala allow operators to be overloaded?



Not really. More precisely, no.

It turns out that everything I read before that is nonsense? This is the stupidest article I have ever read! I hate Scala. Better continue programming on Algol 68.


I'll ask for just a second, I'm not done yet. Scala does not support operator overloading, because Scala simply does not have them!

There are no operators in Scala? You're crazy! So many times I wrote something like "sum = 2 + 3"! But what about the operations "::" and ": /" on lists? They look like operators!


Alas, they are not. The whole point is that Scala does not have strict requirements for what can be called a method.

When you write the following code:

sum = 2 + 3
..., you actually call the + method in the RichInt class of the instance with a value of 2. You can even rewrite the last line as:
sum = 2.+(3)
... if you really want to.

Yeah. Now I understand. So what did you want to tell me about operator overloading there?


It is very simple - as simple as describing a regular method. I will give an example.

class Complex(val real : Double, val imag : Double) {
  def +(that: Complex) =
            new Complex(this.real + that.real, this.imag + that.imag)
  def -(that: Complex) =
            new Complex(this.real - that.real, this.imag - that.imag)
  override def toString = real + " + " + imag + "i"
}
object Complex {
  def main(args : Array[String]) : Unit = {
       var a = new Complex(4.0,5.0)
       var b = new Complex(2.0,3.0)
       println(a)  // 4.0 + 5.0i
       println(a + b)  // 6.0 + 8.0i
       println(a - b)  // 2.0 + 2.0i
  }
}


All this is cool, but what if I want to redefine the operator "not" ("!")?


The difference between this operator and the "+" and "-" operators is that it is unary and prefix. But Scala also supports such, however, in a more limited form than infix operators like "+".

By limited form, I mean the fact that only 4 can be redefined unary prefix operators: "+", "-", "!" and "~". To do this, you need to define the appropriate methods unary_ !, unary_ ~, etc. in the class.

The following example illustrates how to define the ~ operator for complex numbers, which returns the modulus of this number:

class Complex(val real : Double, val imag : Double) {
    // ...
    def unary_~ = Math.sqrt(real * real + imag * imag)
}
object Complex {
  def main(args : Array[String]) : Unit = {
     var b = new Complex(2.0,3.0)
     prinln(~b) //  3.60555
   }
}


Finally

As you can see, overloading operators in Scala is very simple. But please use this opportunity wisely . Do not define methods like “+” in a class, unless your class can do something that can be interpreted as addition or summation.

Original article - Tom Jefferys, “Operator Overloading” in Scala

Also popular now: