- PVSM.RU - https://www.pvsm.ru -
Можно долго спорить, является ли возможность перегружать операторы сильной или слабой стороной конкретного языка. Но факт остается фактом — в Scala такая возможность есть. Так почему бы её не использовать?
Материал статьи рассчитан в основном на начинающих Scala-разработчиков.
Итак, что же такое перегрузка операторов?
В общем случае, операторы — это давно знакомые Вам "+", "-", "*", "!" и множество других. При чем иногда один и тот же оператор может вести себя по разному в зависимости от того, чем он оперирует (например, + как взятие суммы целых чисел и + как операция конкатенации строк). Идея перегрузки операторов проста — если поведение оператора меняется в зависимости от класса объектов, с которым он работает, то почему бы не определить ему новое поведение конкретно для Вашего класса?
Перегрузка операторов — тема довольно противоречивая. Часто говорят, что это является причиной многих злоупотреблений, и эту возможность в С++ так оклеветали, что создатели языка Java сознательно отказались от нее (за исключением оператора "+" для конкатенации строк).
Я придерживаюсь немного другого мнения. Если подходить к перегрузке операторов с должной ответственностью, то можно извлечь существенную практическую выгоду. Приведу пример: многие объекты можно складывать вместе или суммировать, так почему бы просто не использовать оператор "+"?
Допустим, Вы писали класс для комплексных чисел, и Вы хотите, чтобы комплексные числа можно было складывать. Не правда ли, приятнее написать следующий код:
Complex result = complex1 + complex2;
…, чем…
Complex result = complex1.add(complex2);
Первая строчка выглядит естественнее, не так ли?
Не совсем. Точнее говоря, нет.
Попрошу всего секунду, я еще не закончил. Scala не поддерживает перегрузку операторов, потому что в Scala их попросту нет!
Увы, они ими не являются. Вся суть в том, что у Scala нет жестких требований к тому, что можно назвать методом.
Когда Вы пишите следующий код:
sum = 2 + 3
…, на самом деле Вы вызываете метод + в классе RichInt у экземпляра со значением 2. Можно даже переписать прошлую строчку как:
sum = 2.+(3)
…, если Вам действительно этого хочется.
Это очень просто — так же просто, как и описание обычного метода. Приведу пример.
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
}
}
Отличие этого оператора от операторов "+" и "-" в том, что он является унарным и префиксным. Но Scala поддерживает и такие, правда, в более ограниченной форме, чем инфиксные операторы вроде "+".
Под ограниченной формой я подразумеваю тот факт, что унарных префиксных операторов можно переопределить только 4: "+", "-", "!" и "~". Для этого надо определить в классе соответсвующие методы unary_!, unary_~ и т.д.
Следующий пример иллюстрирует, как определить для комплексных чисел оператор "~", возвращающий модуль этого числа:
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
}
}
Как видно, перегружать операторы в Scala очень просто. Но пожалуйста, используйте эту возможность с умом. Не определяйте в классе методы вроде "+", если только ваш класс не умеет делать нечто, что можно интерпретировать как сложение или суммирование.
Исходная статья — Tom Jefferys, «Operator Overloading» in Scala [1]
Автор: madfriend
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/programmirovanie/6897
Ссылки в тексте:
[1] Исходная статья — Tom Jefferys, «Operator Overloading» in Scala: http://java.dzone.com/articles/operator-overloading-scala
Нажмите здесь для печати.