Gli esempi ovvi di appropriato sovraccarico dell'operatore sono le classi che si comportano nello stesso modo in cui operano i numeri. Quindi classi BigInt (come Jalayn suggerisce), numeri complessi o matrix (come suggerito da Superbest ) hanno tutte le stesse operazioni dei numeri ordinari avere una mappa così bene sugli operatori matematici, mentre le operazioni time (come suggerito da svick ) mappare bene su un sottoinsieme di quelle operazioni.
Un po 'più astrattamente, gli operatori potrebbero essere usati quando si eseguono operazioni impostate come , quindi operator+
potrebbe essere un union , operator-
potrebbe essere un complemento ecc. Questo inizia ad allungare il paradigma, specialmente se si usa l'operatore addizione o moltiplicazione per un'operazione che non è commutativa , come potreste aspettarvi che siano.
C # ha un eccellente esempio di sovraccarico dell'operatore non numerico . Utilizza +=
e -=
per aggiungere e sottrarre delegati , vale a dire registrarli e cancellarli. Funziona bene perché gli operatori +=
e -=
funzionano come ci si aspetterebbe, e questo si traduce in un codice molto più conciso.
Per il purista, uno dei problemi con l'operatore stringa +
è che non è commutativo. "a"+"b"
non è uguale a "b"+"a"
. Comprendiamo questa eccezione per le stringhe perché è così comune, ma come possiamo sapere se usare operator+
su altri tipi sarà commutativo o no? La maggior parte delle persone supporterà che lo sia, a meno che l'oggetto non sia simile a una stringa , ma non si sa mai realmente cosa verrà assunto dalla gente.
Come per le stringhe, anche le debolezze delle matrici sono abbastanza conosciute. È ovvio che Matrix operator* (double, Matrix)
è una moltiplicazione scalare, mentre Matrix operator* (Matrix, Matrix)
sarebbe una moltiplicazione di matrice (cioè una matrice di moltiplicazioni di prodotti a punti) ad esempio.
Allo stesso modo, l'utilizzo di operatori con delegati è talmente lontano dalla matematica che è improbabile che tu faccia quegli errori.
Per inciso, alla conferenza ACCU 2011 , Roger Orr & Steve Love ha presentato una sessione su Alcuni oggetti sono più uguali di altri - uno sguardo ai molti significati di uguaglianza, valore e identità . Le loro diapositive sono scaricabili , come lo è il Appendice sull'uguaglianza in virgola mobile . Riepilogo: Stai molto attento con operator==
, qui si trovano i draghi!
L'overloading dell'operatore è una tecnica semantica molto potente, ma è facile da usare. Idealmente dovresti usarlo solo in situazioni in cui è molto chiaro dal contesto quale sia l'effetto di un operatore sovraccarico. In molti modi a.union(b)
è più chiaro di a+b
, e a*b
è molto più oscuro di a.cartesianProduct(b)
, soprattutto perché il risultato di un prodotto cartesiano sarebbe un SetLike<Tuple<T,T>>
piuttosto che un SetLike<T>
.
I veri problemi con l'overloading dell'operatore arrivano quando un programmatore assume che una classe si comporterà in un modo, ma in realtà si comporta in un altro. Questa sorta di scontro semantico è ciò che sto suggerendo che è importante cercare di evitare.