Kapan menggunakan chaining
Fungsi chaining sebagian besar populer dengan bahasa di mana IDE dengan pelengkapan otomatis adalah tempat umum. Misalnya, hampir semua pengembang C # menggunakan Visual Studio. Oleh karena itu, jika Anda mengembangkan dengan menambahkan rantai # ke metode Anda bisa menjadi penghemat waktu bagi pengguna kelas itu karena Visual Studio akan membantu Anda dalam membangun rantai.
Di sisi lain, bahasa seperti PHP yang sangat dinamis dan seringkali tidak memiliki dukungan lengkapi-otomatis dalam IDE akan melihat lebih sedikit kelas yang mendukung perangkaian. Chaining hanya akan sesuai ketika phpDocs yang benar digunakan untuk mengekspos metode yang dapat dilewati.
Apa itu chaining?
Diberi kelas bernama Foo
dua metode berikut keduanya chainable.
function what() { return this; }
function when() { return new Foo(this); }
Fakta bahwa seseorang adalah referensi ke instance saat ini, dan satu menciptakan instance baru tidak mengubah bahwa ini adalah metode yang dapat dilantai.
Tidak ada aturan emas bahwa metode rantai hanya harus merujuk objek saat ini. Infact, metode yang dapat di rantai dapat melintasi dua kelas yang berbeda. Sebagai contoh;
class B { function When() { return true; } };
class A { function What() { return new B(); } };
var a = new A();
var x = a.What().When();
Tidak ada referensi this
dalam contoh di atas. Kode a.What().When()
adalah contoh rantai. Yang menarik adalah bahwa tipe kelas B
tidak pernah ditugaskan ke variabel.
Metode dirantai ketika nilai pengembaliannya digunakan sebagai komponen ekspresi berikutnya.
Berikut ini beberapa contoh lainnya
// return value never assigned.
myFile.Open("something.txt").Write("stuff").Close();
// two chains used in expression
int x = a.X().Y() * b.X().Y();
// a chain that creates new strings
string name = str.Substring(1,10).Trim().ToUpperCase();
Kapan harus menggunakan this
dannew(this)
String dalam kebanyakan bahasa tidak dapat diubah. Jadi panggilan metode chaining selalu menghasilkan string baru yang dibuat. Di mana sebagai objek seperti StringBuilder dapat dimodifikasi.
Konsistensi adalah praktik terbaik.
Jika Anda memiliki metode yang mengubah keadaan objek dan kembali this
, maka jangan campur dalam metode yang mengembalikan instance baru. Sebaliknya, buat metode spesifik yang disebut Clone()
yang akan melakukan ini secara eksplisit.
var x = a.Foo().Boo().Clone().Foo();
Itu jauh lebih jelas tentang apa yang terjadi di dalam a
.
Langkah Luar Dan Trik Kembali
Saya menyebut ini langkah keluar dan trik, karena ini memecahkan banyak masalah umum yang terkait dengan rantai. Ini pada dasarnya berarti bahwa Anda keluar dari kelas asli ke kelas sementara baru dan kemudian kembali ke kelas asli.
Kelas sementara hanya ada untuk menyediakan fitur khusus ke kelas asli, tetapi hanya dalam kondisi khusus.
Sering kali suatu rantai perlu mengubah keadaan , tetapi kelas A
tidak dapat mewakili semua keadaan yang mungkin . Jadi selama rantai kelas baru diperkenalkan yang berisi referensi kembali ke A
. Ini memungkinkan programmer untuk masuk ke keadaan dan kembali ke A
.
Ini adalah contoh saya, biarkan negara khusus dikenal sebagai B
.
class A {
function Foo() { return this; }
function Boo() { return this; }
function Change() return new B(this); }
}
class B {
var _a;
function (A) { _a = A; }
function What() { return this; }
function When() { return this; }
function End() { return _a; }
}
var a = new A();
a.Foo().Change().What().When().End().Boo();
Nah, itu adalah contoh yang sangat sederhana. Jika Anda ingin memiliki lebih banyak kontrol, maka B
dapat kembali ke tipe super baru A
yang memiliki metode berbeda.
return this
. Bagaimana saya dapat membantu pengguna perpustakaan saya untuk menangani dan memahami situasi ini? (Mengizinkan mereka menggunakan metode berantai, bahkan ketika itu tidak diperlukan, apakah ini benar-benar baik-baik saja? Atau haruskah saya hanya berpegang teguh pada satu cara, memerlukan perubahan sama sekali?)Bergantung pada bahasanya, memiliki metode yang mengembalikan
void
/unit
dan memodifikasi instance atau parameternya adalah non-idiomatis. Bahkan dalam bahasa yang digunakan untuk melakukan itu lebih banyak (C #, C ++), itu keluar dari mode dengan pergeseran ke arah pemrograman gaya yang lebih fungsional (objek abadi, fungsi murni). Tapi mari kita asumsikan ada alasan bagus untuk saat ini.Untuk perilaku tertentu (pikirkan
x++
) diharapkan operasi mengembalikan hasilnya, meskipun memodifikasi variabel. Tapi itu satu-satunya alasan untuk melakukannya sendiri.Tergantung.
Dalam bahasa di mana salin / baru dan kembali adalah umum (C # LINQ dan string) maka mengembalikan referensi yang sama akan membingungkan. Dalam bahasa di mana memodifikasi dan mengembalikan adalah umum (beberapa perpustakaan C ++) maka penyalinan akan membingungkan.
Membuat tanda tangan tidak ambigu (dengan mengembalikan
void
atau menggunakan konstruksi bahasa seperti properti) akan menjadi cara terbaik untuk memperjelas. Setelah itu, buat namanya jelasSetFoo
untuk menunjukkan bahwa Anda memodifikasi instance yang ada adalah baik. Tetapi kuncinya adalah mempertahankan idiom bahasa / perpustakaan yang Anda gunakan.sumber
Clear()
atauAdd()
dari jenis koleksi apa pun akan memodifikasi contoh yang sama dan kembalivoid
. Dalam kedua kasus Anda mengatakan itu akan membingungkan ...obj = myCollection.Where(x => x.MyProperty > 0).OrderBy(x => x.MyProperty);
?Where()
mengembalikan objek koleksi baru.OrderBy()
bahkan mengembalikan objek koleksi yang berbeda, karena kontennya dipesan.IEnumerable
, tetapi untuk menjadi jelas, mereka tidak salinan, dan mereka tidak koleksi (kecuali untukToList
,ToArray
, dll).ICollection
. Salahku.(Saya menganggap C ++ sebagai bahasa pemrograman Anda)
Bagi saya ini sebagian besar merupakan aspek keterbacaan. Jika A, B, C adalah pengubah, terutama jika ini adalah objek sementara yang dilewatkan sebagai parameter untuk beberapa fungsi, misalnya
dibandingkan dengan
Mendaftarkan kembali jika tidak masalah untuk mengembalikan referensi ke instance yang dimodifikasi, saya akan mengatakan ya, dan mengarahkan Anda sebagai contoh ke operator streaming '>>' dan '<<' ( http://www.cprogramming.com/tutorial/ operator_overloading.html )
sumber
Anda juga bisa melakukan metode chaining hal dengan copy return daripada memodifikasi return.
Contoh C # yang baik adalah string. Ganti (a, b) yang tidak mengubah string tempat ia dipanggil tetapi sebaliknya mengembalikan string baru yang memungkinkan Anda untuk rantai menjauh dengan riang.
sumber