Sementara saya belajar C #, saya menemukan bahwa, C # mendukung overloading operator. Saya punya masalah dengan contoh bagus yang:
- Masuk akal (mis. Menambahkan kelas bernama domba dan sapi)
- Bukan contoh gabungan dari dua string
Contoh dari Perpustakaan Kelas Dasar dipersilakan.
==
melakukan multiplikasi, itu masuk akal bagi saya tetapi mungkin tidak masuk akal bagi orang lain! Apakah pertanyaan ini tentang legitimasi bahasa pemrograman fasilitas apa atau apakah kita berbicara tentang 'pengkodean praktik terbaik'?Jawaban:
Contoh nyata dari overloading operator yang tepat adalah setiap kelas yang berperilaku dengan cara yang sama seperti angka beroperasi. Jadi BigInt kelas (sebagai Jalayn menyarankan), bilangan kompleks atau matriks kelas (sebagai Superbest menyarankan) semua memiliki operasi yang sama yang nomor biasa telah begitu memetakan dengan sangat baik ke operator matematika, sementara waktu operasi (seperti yang disarankan oleh svick ) map baik ke subset dari operasi tersebut.
Sedikit lebih abstrak, operator dapat digunakan ketika melakukan operasi seperti set , sehingga
operator+
bisa menjadi gabungan ,operator-
bisa menjadi pelengkap, dll. Ini memang mulai memperluas paradigma, terutama jika Anda menggunakan operator penambahan atau gandakan untuk operasi yang tidak t komutatif , seperti yang Anda harapkan.C # sendiri memiliki contoh kelebihan operator non-numerik . Ia menggunakan
+=
dan-=
untuk menambah dan mengurangi delegasi , yaitu mendaftar dan tidak mendaftar. Ini bekerja dengan baik karena operator+=
dan-=
bekerja seperti yang Anda harapkan, dan ini menghasilkan kode yang lebih ringkas.Untuk purist, salah satu masalah dengan
+
operator string adalah ia tidak komutatif."a"+"b"
tidak sama dengan"b"+"a"
. Kami memahami pengecualian untuk string ini karena itu sangat umum, tetapi bagaimana kami bisa tahu apakah menggunakanoperator+
pada tipe lain akan komutatif atau tidak? Kebanyakan orang akan berasumsi bahwa itu adalah, kecuali objeknya seperti string , tetapi Anda tidak pernah benar-benar tahu apa yang akan diasumsikan orang.Seperti halnya string, kelemahan matriks juga cukup terkenal. Jelas bahwa itu
Matrix operator* (double, Matrix)
adalah perkalian skalar, sedangkanMatrix operator* (Matrix, Matrix)
akan menjadi perkalian matriks (yaitu matriks perkalian titik-produk) misalnya.Demikian pula penggunaan operator dengan delegasi jelas sekali jauh dari matematika sehingga Anda tidak mungkin membuat kesalahan itu.
Kebetulan, pada konferensi ACCU 2011 , Roger Orr & Steve Love mempresentasikan sesi tentang beberapa objek yang lebih setara daripada yang lain - lihat banyak makna persamaan, nilai, dan identitas . Slide-slide mereka dapat diunduh , seperti Lampiran Richard Harris tentang kesetaraan floating point . Ringkasan: Berhati-hatilah dengan
operator==
, ini naga!Overloading operator adalah teknik semantik yang sangat kuat, tetapi mudah digunakan secara berlebihan. Idealnya Anda hanya boleh menggunakannya dalam situasi ketika sangat jelas dari konteks apa efek dari operator kelebihan beban. Dalam banyak hal
a.union(b)
lebih jelas daripadaa+b
, dana*b
adalah jauh lebih jelas daripadaa.cartesianProduct(b)
, terutama karena hasil produk Cartesian akan menjadiSetLike<Tuple<T,T>>
daripadaSetLike<T>
.Masalah sebenarnya dengan overloading operator datang ketika seorang programmer menganggap suatu kelas akan berperilaku dalam satu cara, tetapi sebenarnya berperilaku di lain. Bentrokan semantik semacam ini adalah apa yang saya sarankan penting untuk dihindari.
sumber
d1 + d2
untuk dua delegasi dengan tipe yang sama.Saya terkejut tidak ada yang menyebutkan salah satu kasus yang lebih menarik di BCL:
DateTime
danTimeSpan
. Kamu bisa:TimeSpan
s untuk mendapatkan yang lainTimeSpan
TimeSpan
untuk mendapatkan negasiTimeSpan
DateTime
s untuk mendapatkanTimeSpan
TimeSpan
dariDateTime
untuk mendapatkan yang lainDateTime
Set operator yang bisa masuk akal pada banyak jenis yang
<
,>
,<=
,>=
. Di BCL, misalnyaVersion
mengimplementasikannya.sumber
Contoh pertama yang muncul di benak saya adalah implementasi BigInteger , yang memungkinkan Anda untuk bekerja dengan bilangan bulat bertanda besar. Lihat tautan MSDN untuk melihat berapa banyak operator yang kelebihan beban (yaitu, ada daftar besar, dan saya tidak memeriksa apakah semua operator kelebihan beban, tapi sepertinya begitu)
Juga, karena saya juga melakukan Java dan Java tidak memungkinkan operator overload, itu sangat manis untuk menulis
Daripada di Jawa:
sumber
Saya senang melihat ini karena saya telah bermain-main dengan Irony dan memiliki penggunaan operator yang berlebihan. Berikut adalah contoh apa yang dapat dilakukannya.
Jadi Irony adalah ".NET Language Implementation Kit" dan merupakan parser generator (menghasilkan parser LALR). Alih-alih harus mempelajari sintaks / bahasa baru seperti generator parser seperti yacc / lex Anda menulis tata bahasa di C # dengan operator kelebihan. Berikut ini adalah tata bahasa BNF sederhana
Jadi ini adalah tata bahasa kecil yang sederhana (permisi jika ada ketidakkonsistenan karena saya baru belajar BNF dan membuat tata bahasa). Sekarang mari kita lihat C #:
Seperti yang Anda lihat, dengan operator kelebihan, menulis tata bahasa di C # hampir persis menulis tata bahasa di BNF. Bagi saya, itu tidak hanya masuk akal tetapi juga penggunaan berlebihan operator.
sumber
Contoh kuncinya adalah operator == / operator! =.
Jika Anda ingin dengan mudah membandingkan dua objek dengan nilai data alih-alih dengan referensi, Anda akan ingin membebani .Equals (and.GetHashCode!), Dan mungkin ingin melakukan operator! = Dan == juga untuk konsistensi.
Saya belum pernah melihat kelebihan liar dari operator lain di C # (saya membayangkan ada kasus tepi di mana mungkin berguna).
sumber
Contoh dari MSDN ini menunjukkan bagaimana menerapkan bilangan kompleks dan meminta mereka menggunakan operator + normal.
Contoh lain menunjukkan bagaimana melakukannya untuk penambahan matriks, dan juga menjelaskan bagaimana tidak menggunakannya untuk menambahkan mobil ke garasi (baca tautannya).
sumber
Penggunaan kelebihan muatan yang baik bisa jarang terjadi, tetapi itu memang terjadi.
operator overloading == dan operator! = menunjukkan dua aliran pemikiran: yang untuk mengatakan hal itu membuat segalanya lebih mudah, dan mereka yang menolak mengatakan hal itu mencegah membandingkan alamat (yaitu saya menunjuk ke tempat yang persis sama dalam memori, bukan hanya salinan yang sama obyek).
Saya merasa operator overload berguna dalam situasi tertentu. Sebagai contoh, saya harus membuat serial / deserialize dalam XML boolean direpresentasikan sebagai 0 atau 1. Hak (implisit atau eksplisit, saya lupa) melemparkan operator dari boolean ke int dan kembali melakukan trik.
sumber
object.ReferenceEquals()
.==
dengan melakukan casting:(object)foo == (object)bar
selalu membandingkan referensi. Tapi saya lebih sukaReferenceEquals()
, seperti @ dan04 menyebutkan karena lebih jelas apa fungsinya.Mereka tidak termasuk dalam kategori hal-hal yang biasanya dipikirkan orang ketika mereka melakukan overloading pada operator, tapi saya pikir salah satu operator yang paling penting untuk dapat overload adalah operator konversi .
Operator konversi sangat berguna untuk tipe nilai yang dapat "mengurangi gula" menjadi tipe numerik, atau dapat bertindak seperti tipe numerik dalam beberapa konteks. Sebagai contoh, Anda mungkin mendefinisikan khusus
Id
jenis yang mewakili pengenal tertentu, dan Anda bisa memberikan implisit konversi keint
sehingga Anda dapat melewatiId
ke metode yang mengambil sebuahint
, tapi explict konversi dariint
keId
sehingga tidak ada yang bisa lulusint
menjadi metode yang membutuhkanId
tanpa casting terlebih dahulu.Sebagai contoh di luar C #, bahasa Python mencakup banyak perilaku khusus yang diterapkan sebagai operator yang kelebihan beban. Ini termasuk
in
operator untuk pengujian keanggotaan,()
operator untuk memanggil objek seolah-olah itu fungsi, danlen
operator untuk menentukan panjang atau ukuran suatu objek.Dan kemudian Anda memiliki bahasa seperti Haskell, Scala, dan banyak bahasa fungsional lainnya, di mana nama seperti
+
hanya fungsi biasa, dan bukan operator sama sekali (dan ada dukungan bahasa untuk menggunakan fungsi dalam posisi infix).sumber
The Titik Struct di System.Drawing namespace menggunakan overloading untuk membandingkan dua lokasi yang berbeda menggunakan operator overloading.
Seperti yang Anda lihat, jauh lebih mudah untuk membandingkan koordinat X dan Y dari dua lokasi menggunakan kelebihan beban.
sumber
Jika Anda terbiasa dengan vektor matematika Anda mungkin melihat kegunaan dalam membebani
+
operator. Anda dapat menambahkan vektora=[1,3]
denganb=[2,-1]
dan dapatkanc=[3,2]
.Kelebihan yang sama dengan (==) juga bisa menjadi berguna (meskipun mungkin lebih baik untuk menerapkan
equals()
metode). Untuk melanjutkan contoh-contoh vektor:sumber
Bayangkan sepotong kode untuk menggambar pada formulir
Contoh umum lainnya adalah ketika struktur digunakan untuk menyimpan informasi posisi dalam bentuk vektor.
hanya untuk digunakan nanti sebagai
sumber
operator+
seharusnya tidak kelebihan beban (Anda dapat menerapkan titik dalam hal vektor, tetapi Anda tidak harus mampu menambah dua poin)p1+((p2-p1)+(p3-p1)+(p4-p1))/4
, tetapi itu tampaknya agak canggung.