Dart позволяет изменить поведение ряда встроенных операторов, что позволяет нам воспользоваться дополнительными возможностями по работе с объектами. Например, пусть у нас есть следующий класс Counter:
class Counter{ int value; Counter(this.value); }
Данный класс представляет некоторый счетчик, значение которого хранится в поле value.
И допустим, у нас есть два объекта класса Counter - два счетчика, которые мы хотим сравнивать или складывать на основании их поля value, используя стандартные операции сравнения и сложения:
Counter counter1 = Counter(5); Counter counter2 = Counter(15); Counter counter3 = counter1 + counter2; bool isFirstGreater = counter1 > counter2;
Но по умолчанию ни операция сравнения, ни операция сложения для объектов Counter не доступны. Эти операции можно использовать с объектами примитивных типов, например, int. Но как складывать объекты классов, определенных разработчиком, Dart не знает. И для этого нам надо переопределить соответствующие операторы.
Переопределение операторов заключается в определении в классе, для объектов которого мы хотим определить оператор, специального метода:
возвращаемый_тип operator оператор(параметр) { }
Возвращаемый тип представляет тот тип, объекты которого мы хотим получить. К примеру, в результате сложения двух объектов Counter мы ожидаем получить новый объект Counter. А в результате сравнения двух мы хотим получить объект типа bool, который указывает истинно ли условное выражение или ложно. Но в зависимости от задачи возвращаемые типы могут быть любыми. Затем вместо названия метода идет ключевое слово operator и собственно сам оператор. И далее в скобках указывается параметр.
Например, перегрузим оператор сложения для класса Counter:
void main (){ Counter counter1 = Counter(5); Counter counter2 = Counter(15); Counter counter3 = counter1 + counter2; print(counter3.value); // 20 } class Counter{ int value; Counter(this.value); Counter operator +(Counter otherCounter){ return Counter(this.value + otherCounter.value); } }
в случае с операцией сложения мы хотим сложить два объекта класса Counter, то оператор принимает в качестве параметра объект этого класса. И так как мы хотим в результате сложения получить новый объект Counter, то данный класс также используется в качестве возвращаемого типа. Все действия этого оператора сводятся к созданию, нового объекта, поле value которого объединяет значения поля value обоих объектов.
Следует отметить, что мы не можем переопределить абсолютно все имеющиеся в Dart операторы, а только некоторые из них, а именно: < + | [] > / ^ []= <= ~/ & ~ >= * << == – % >>
Например, переопределим для класса Counter еще и операторы > и <:
void main (){ Counter counter1 = Counter(5); Counter counter2 = Counter(15); bool isFirstGreater = counter1 > counter2; print(isFirstGreater); // false bool isFirstLess = counter1 < counter2; print(isFirstLess); // true } class Counter{ int value; Counter(this.value); Counter operator +(Counter otherCounter){ return Counter(this.value + otherCounter.value); } bool operator >(Counter otherCounter) => this.value > otherCounter.value; bool operator <(Counter otherCounter) => this.value < otherCounter.value; }
Поскольку операции < и > возвращают значение типа bool, то и здесь при опеределении оператора возвращаемый тип bool, а фактическое действие оператора сводится к сравнению значений полей value обоих объектов.
Хотя в примерах выше в качестве параметра передавался объект того же типа - Counter, это необязательно, в зависимости от нашей задачи параметр может представлять любой тип. Например, изменим код следующим образом:
void main (){ Counter counter1 = Counter(15); Counter counter2 = counter1 + 25; print(counter2.value); // 40 int diff = counter1 - 7; print(diff); // 8 } class Counter{ int value; Counter(this.value); Counter operator +(int number){ return Counter(this.value + number); } int operator -(int number){ return this.value - number; } }
Теперь оператор сложения позволяет складывать объект Counter и обычное число и возвращает новый объект Counter. А оператор вычитания позволяет вычитать из Counter число и возвращает другое - разность поля value и вычитаемого числа.