Katakanlah kita membuat pengurai. Satu implementasi dapat:
public sealed class Parser1
{
public string Parse(string text)
{
...
}
}
Atau sebaliknya, kami dapat meneruskan teks ke konstruktor:
public sealed class Parser2
{
public Parser2(string text)
{
this.text = text;
}
public string Parse()
{
...
}
}
Penggunaannya sederhana dalam kedua kasus, tetapi apa artinya mengaktifkan input parameter Parser1
, dibandingkan dengan yang lain? Pesan apa yang saya kirim ke sesama programmer, ketika mereka melihat API? Juga, apakah ada kelebihan / kekurangan teknis dalam kasus-kasus tertentu?
Pertanyaan lain muncul ketika saya menyadari bahwa antarmuka akan sangat tidak berarti dalam implementasi kedua:
public interface IParser
{
string Parse();
}
... di mana antarmuka pada antarmuka pertama dapat melayani setidaknya beberapa tujuan. Apakah itu menandakan sesuatu yang khusus, bahwa suatu kelas "antarmuka" atau tidak?
object-oriented
interfaces
methods
construction
ciscoheat
sumber
sumber
Jawaban:
Semantik berbicara, dalam OOP Anda hanya harus melewati konstruktor seperangkat parameter yang diperlukan untuk membangun kelas - sama ketika Anda memanggil suatu metode, Anda hanya harus memberikan parameter yang diperlukan untuk mengeksekusi logika bisnisnya.
Parameter yang harus Anda lewati di konstruktor adalah parameter yang tidak memiliki nilai default yang masuk akal dan jika kelas Anda tidak dapat diubah (atau memang a
struct
) maka semua properti non-default harus dilewati.Mengenai dua contoh Anda:
text
ke konstruktor, itu mengisyaratkan bahwaParser2
kelas akan dibangun secara khusus untuk mem-parsing instance teks itu di lain waktu. Ini akan menjadi parser khusus. Ini biasanya terjadi ketika membangun kelas sangat mahal atau halus, sebuah RegEx mungkin dikompilasi dalam konstruktor, jadi setelah Anda memegang contoh Anda dapat menggunakannya kembali tanpa harus membayar biaya kompilasi; contoh lain adalah menginisialisasi PRNG - lebih baik jika dilakukan jarang.text
ke metode, itu menandakan yangParser1
dapat digunakan kembali untuk mem-parsing teks yang berbeda melalui panggilan.sumber
Nah, mari kita ingat apa artinya melewatkan variabel sebagai parameter konstruktor: Anda menginisialisasi objek untuk menggunakan variabel instansinya dalam metode objek. Intinya adalah Anda mungkin ingin menggunakannya dalam lebih dari satu metode karena Anda ingin memiliki kohesi yang tinggi di kelas Anda.
Melewati parameter langsung ke metode berarti dengan cara mengirim pesan ke objek dan mungkin menerima jawaban. Dengan itu, klien menginginkan objek untuk memberikan layanan untuknya.
Jadi sebagai kesimpulan, itu adalah dua cara yang sangat berbeda untuk melewatkan parameter dan Anda harus memilih apakah objek Anda harus memberikan layanan atau menyediakan beberapa fungsi secara inheren sambil mengelola beberapa informasi secara internal.
sumber
Ini adalah perubahan desain mendasar. Dan desain harus menyampaikan maksud dan makna. Apakah Anda perlu memiliki objek terpisah untuk setiap string yang ingin Anda parsing? Dengan kata lain, mengapa kita membutuhkan instance parser dengan stringX dan contoh lain dengan stringY? Ada apa dengan parse (ing) dan string yang diberikan bahwa keduanya harus hidup dan mati bersama? Dengan asumsi bahwa "implementasi [parsing] yang mendasarinya" (seperti yang dikatakan Robert Harvey) tidak berubah, tampaknya tidak ada gunanya. Dan itupun IMHO dipertanyakan.
Parameter konstruktor memberi tahu saya hal-hal ini diperlukan untuk suatu objek. Status yang tepat tidak dijamin tanpa mereka. Juga, saya tahu bagaimana / mengapa satu parser secara fundamental berbeda dari yang lain.
Parameter konstruktor membuat saya tidak perlu tahu terlalu banyak tentang cara menggunakan kelas. Jika sebaliknya saya seharusnya menetapkan properti tertentu - bagaimana saya tahu itu? Segelas cacing terbuka. Sifat apa? Dalam urutan apa? Sebelum saya menggunakan metode apa? dan seterusnya.
Antarmuka, seperti dalam API, adalah metode dan properti yang diekspos ke kode klien. Jangan terlibat secara
public interface { ... }
eksklusif. Jadi arti dari antarmuka adalah dilema parameter baik-atau konstruktor vs metode, TIDAKpublic interface Iparser
vspublic sealed class Parser
The
sealed
kelas aneh. Jika saya berpikir tentang implementasi parser yang berbeda - Anda memang menyebutkan "Iparser" - maka warisan adalah pikiran pertama saya. Itu hanya perpanjangan konseptual yang alami dalam pemikiran saya. IE semuaParserX
s pada dasarnyaParser
s. Bagaimana cara mengatakannya? ... German Shepard adalah seekor anjing (warisan), tetapi saya dapat melatih burung beo saya untuk menggonggong (bertindak seperti anjing - "antarmuka"); tetapi Polly bukan seekor anjing, hanya berpura-pura, telah belajar sebagian dari dogness. Kelas, abstrak atau lainnya, berfungsi dengan baik sebagai antarmuka .sumber
Versi kedua dari kelas dapat dibuat tidak berubah.
Antarmuka masih dapat digunakan untuk memberikan kemampuan untuk menukar implementasi yang mendasarinya.
sumber
Parser1
Bangunan dengan konstruktor default dan meneruskan input teks ke dalam metode menyiratkan bahwa Parser1 dapat digunakan kembali.
Parser2
Melewati teks input ke konstruktor menyiratkan bahwa Parser2 baru harus dibuat untuk setiap string input.
sumber