Gli esempi ovvi di sovraccarico appropriato da parte dell'operatore sono le classi che si comportano nello stesso modo in cui operano i numeri. Quindi le classi di BigInt (come suggerisce Jalayn ), i numeri complessi o le classi di matrici (come suggerisce Superbest ) hanno tutte le stesse operazioni che i numeri ordinari hanno così ben mappato sugli operatori matematici, mentre le operazioni di tempo (come suggerito da svick ) si associano bene su un sottoinsieme di tali operazioni.
Leggermente più astrattamente, gli operatori potrebbero essere utilizzati quando si eseguono operazioni come set , quindi operator+
potrebbe essere un'unione , operator-
potrebbe essere un complemento ecc. Questo però inizia a estendere il paradigma, soprattutto se si utilizza l'operatore addizione o moltiplicazione per un'operazione che non è t commutativo , come ci si potrebbe aspettare che siano.
C # stesso ha un eccellente esempio di sovraccarico dell'operatore non numerico . Usa +=
e -=
per aggiungere e sottrarre delegati , cioè registrarli e cancellarli. Funziona bene perché gli operatori +=
e -=
funzionano come ci si aspetterebbe da loro, 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 è lo stesso di "b"+"a"
. Comprendiamo questa eccezione per le stringhe perché è così comune, ma come possiamo sapere se l'utilizzo operator+
su altri tipi sarà commutativo o no? La maggior parte delle persone supporrà che lo sia, a meno che l'oggetto non sia simile a una stringa , ma non si sa mai veramente cosa assumeranno le persone.
Come per le stringhe, anche le debolezze delle matrici sono abbastanza conosciute. È ovvio che si Matrix operator* (double, Matrix)
tratta di una moltiplicazione scalare, mentre Matrix operator* (Matrix, Matrix)
sarebbe ad esempio una moltiplicazione di matrice (cioè una matrice di moltiplicazioni di punti-prodotto).
Allo stesso modo, l'uso di operatori con delegati è così chiaramente rimosso dalla matematica che è improbabile che tu commetta questi errori.
Per inciso, alla conferenza ACCU del 2011 , Roger Orr e Steve Love hanno 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 , così come l' appendice di Richard Harris sull'uguaglianza in virgola mobile . Sommario: Essere molto attenti con operator==
, hic sunt leones!
Il sovraccarico dell'operatore è una tecnica semantica molto potente, ma è facile da usare eccessivamente. 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
, ed 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 il sovraccarico dell'operatore arrivano quando un programmatore presume che una classe si comporti in un modo, ma in realtà si comporti in un altro. Questo tipo di scontro semantico è ciò che sto suggerendo che è importante cercare di evitare.