Переопределение операторов

Последнее обновление: 09.04.2023

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 и вычитаемого числа.

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850