Очевидними прикладами відповідного перевантаження оператора є будь-які класи, які ведуть себе так, як діють числа. Тож класи BigInt (як пропонує Джалайн ), складні числа або матричні класи (як пропонує Superbest ) усі мають ті ж операції, що звичайні числа так добре відображаються на математичних операторах, тоді як операції з часом (як пропонує Svick ) добре відображають на підмножину цих операцій.
Трохи більш абстрактно, операторів можна використовувати при виконанні операцій, встановлених на зразок , так що це operator+
може бути об'єднання , operator-
може бути доповненням і т. Д. Це дійсно починає розтягувати парадигму, особливо якщо ви використовуєте оператор додавання або множення для операції, яка не є ' t комутативні , як ви могли їх очікувати.
Сам C # є прекрасним прикладом нечислового перевантаження оператора. Він використовує +=
та -=
додає та віднімає делегатів , тобто реєструє та скасовує їх. Це добре працює , тому що +=
і -=
оператори працюють , як можна було б очікувати їх до, і цей результат в набагато більш лаконічному коді.
Для пуристів одна з проблем +
оператора рядків полягає в тому, що він не є комутативним. "a"+"b"
не те саме, що "b"+"a"
. Ми розуміємо цей виняток для рядків, оскільки він настільки поширений, але як ми можемо визначити, чи використання operator+
інших типів буде комутативним чи ні? Більшість людей вважають, що це так, якщо об'єкт не є стрункоподібним , але ви ніколи не знаєте, що припускатимуть люди.
Як і у випадку з рядками, досить добре відомі також і байки матриць. Очевидно, що Matrix operator* (double, Matrix)
це скалярне множення, тоді як, наприклад, Matrix operator* (Matrix, Matrix)
було б матричне множення (тобто матриця множення крапкових продуктів).
Аналогічно використання операторів з делегатами настільки далеко від математики, що ви навряд чи помилитесь.
До речі, на конференції ACCU 2011 року Роджер Орр та Стів Лав представили сесію на тему: Деякі об'єкти є більш рівними, ніж інші - погляд на багато значень рівності, цінності та ідентичності . Їх слайди можна завантажити , як і Додаток Річарда Гарріса про рівність з плаваючою комою . Резюме: Будьте дуже обережні з operator==
, тут дракони!
Перевантаження оператора - це дуже потужна семантична техніка, але її легко використовувати. В ідеалі ви повинні використовувати його лише в тих ситуаціях, коли з контексту зрозуміло, який вплив перевантажений оператор. Багато в чому a.union(b)
це ясніше , ніж a+b
та a*b
є набагато більш неясним , ніж a.cartesianProduct(b)
, тим більше , що результат декартова твори буде , SetLike<Tuple<T,T>>
а не SetLike<T>
.
Справжні проблеми з перевантаженням оператора виникають тоді, коли програміст припускає, що клас буде вести себе в один спосіб, але він насправді веде себе по-іншому. Такого роду смислові зіткнення - це те, що я припускаю, що важливо намагатися уникати.