Как современный язык программирования, Dart предлагает разработчикам множество тонкостей и синтаксического сахара. В последнее время я довольно часто начал использовать перегрузку операторов, чтобы добавить легко читаемую функциональность классам в моей модели.
Перегрузка оператора
Для тех, кто не слышал об этом, позвольте мне объяснить, что это на самом деле.
Перегрузка операторов дает вам возможность добавлять собственные реализации к определенному набору операторов в ваших классах. Эти операторы могут быть:
- Арифметические операторы, такие как
+
-
*
и т. Д. - Операторы равенства, такие как
==
и!=
- Операторы отношения,
>
>=
<
и<=
- и многое другое
Эту языковую функцию также можно найти в других языках, таких как Kotlin, Groovy, C ++ и т. Д.
Например, у нас есть приложение с двумя классами Person
и Family
. Перегрузив оператор плюса, мы получим следующее:
Family family = new Person() + new Person();
Для этого у нас должны быть следующие классы:
class Person { Family operator +(Person other) { return Family([this, other]); } } class Family { final List<Person> people; Family(this.people); }
Давайте подробнее рассмотрим код, который перегружает оператор.
Family operator +(Person other) { return Family([this, other]); }
Мы используем зарезервированное ключевое слово operator
и конкретный оператор, который мы хотим перегрузить, в данном случае оператор плюс: +
В качестве возвращаемого типа мы определяем Family
. В теле функции мы просто создаем объект Family
, передавая литерал List
с обоими объектами Person
.
Порядок операндов идет слева направо, что означает, что this
- это левый Person
, а other
- правый.
Другой пример
Может быть, вы думаете, это полезно? Что ж, семейный пример на самом деле не лучший вариант использования, но я смог использовать его с пользой, когда делал приложение Flutter, чтобы отслеживать потребление коммунальных услуг в доме.
class MeterReading { final double electricity; final double gas; final double water; MeterReading({this.electricity, this.gas, this.water}); Consumption operator -(MeterReading other) => Consumption( electricity: (electricity - other.electricity).abs(), gas: (gas - other.gas).abs(), water: (water - other.water).abs() ); }
Перегрузив оператор минус, я смог использовать этот синтаксический сахар в своих функциях вычисления:
Consumption consumption = reading - previousReading;
Еще мне нужно было использовать множитель. Если бы потребление было измерено между 10 марта и 10 апреля, мне пришлось бы умножить потребление примерно на 0,67, чтобы получить частичное потребление за март. Впоследствии я мог бы добавить это к потреблению за первые 10 дней марта, перегрузив оператор плюс.
// Consumption.dart Consumption operator *(double multiplier) => Consumption( electricity: electricity * multiplier, gas: gas * multiplier, water: water * multiplier, ); Consumption operator +(Consumption other) => Consumption( electricity: electricity + other?.electricity, gas: gas + other?.gas, water: water + other?.water, );
Порядок операторов
Во время разработки этого инструмента я неожиданно получил неожиданные результаты.
Consumption one = Consumption(electricity: 15, gas: 3, water: 9); Consumption two = Consumption(electricity: 5, gas: 7, water: 11); Consumption result = one + two * 0.5; print("Result is $result");
Я ожидал получить следующий результат:
›Результат - электричество: 10,0, газ: 5,0, вода: 10,0
Вместо этого я получил:
› Результат: электричество: 17,5, газ: 6,5, вода: 14,5.
Причина этого в том, что эти операторы по-прежнему имеют определенный приоритет операций. Это заставило приведенный выше код сначала выполнить two * 0.5
, а затем выполнить операцию плюса. Добавление круглых скобок устранило эту проблему.
Consumption result = (one + two) * 0.5
Больше операторов
Помимо тех, что я показал, в Dart есть намного больше операторов, которые можно переопределить для пользовательских реализаций.
Следует упомянуть два интересных аспекта: оператор доступа к списку []
и оператор вызова функции ()
путем реализации call()
. Это может помочь добавить больше синтаксического сахара в вашу модель или даже создать предметно-ориентированный язык в Dart.
Узнайте больше о перегрузке операторов в Dart в документации и дайте мне знать, как вы их используете! :-)