Многие знают, что в Scala возможна перегрузка операторов.
К примеру, пусть у нас будет класс – двухмерная точка:
class Point(val x: Double, val y: Double) {
def -(p: Point) = new Point(x-p.x, y-p.y);
def +(p: Point) = new Point(x+p.x, y+p.y);
}
Работать с ней приятно:
val p1 = new Point(2,2);
val p2 = new Point(1,1);
val p = p2 - p1;
Но что делать, если хочется определить унарный минус, т.е. чтобы можно было писать вот так:
val p = new Point(2,2);
val antiP = -p;
Конечно, вы можете попробовать сделать так:
// ТАК ДЕЛАТЬ НЕ НАДО!
def -() = new Point(-x,-y);
Такой код конечно скомпилируется, но тогда и пользоваться им придется следующим образом:
val antiP = p-;
Что же делать?
Этот случай в спецификации языка Scala описан в разделе 6.12.1 Prefix Operations.
В таких ситуациях следует использовать магическую фразу “unary_”!
Она работает только для четырех операторов: -, +, ~, !.
Таким образом, дополнив нашу точку следующим методом:
class Point(val x: Double, val y: Double) {
def unary_-() = new Point(-x,-y);
def -(p: Point) = new Point(x-p.x, y-p.y);
def +(p: Point) = new Point(x+p.x, y+p.y);
}
Мы можем делать следующие вещи:
val antiP = -p;
Таким образом оператор стал префиксным.
Ради научного интереса Вы можете переопределить еще парочку операторов, например !p – получить точку симметричную относительно оси Y, ~p – относительно оси X, создав таким образом целый “зоопарк” прикольных операторов.
class Point(val x: Double, val y: Double) {
// !p | p
// ---------
// -p | ~p
def unary_-() = new Point(-x,-y);
def unary_!() = new Point(-x,y);
def unary_~() = new Point(x,-y);
def -(p: Point) = new Point(x-p.x, y-p.y);
def +(p: Point) = new Point(x+p.x, y+p.y);
}
Конечно можно еще для полноты ощущений перегрузить унарный плюс (unary_+), но это на любителя.
Что касается других операторов (кроме -,+,~,!), то на них “unary_” не действует. Вам никто не запретит сделать метод unary_*, но автоматически становится префиксным он не будет. Другими словами вызов *p – не сработает, а сработает только p.unary_*(). Думаю, это не то, что вам хотелось.
Кстати, работает как -p, так и p.unary_-(). Метод unary_-() никуда не делся, просто у нас появился еще один (более простой) способ его вызвать.