Apa perbedaan antara kedua metode UpdateSubject di bawah ini? Saya merasa menggunakan metode statis lebih baik jika Anda hanya ingin beroperasi pada entitas. Dalam situasi apa saya harus menggunakan metode non-statis?
public class Subject
{
public int Id {get; set;}
public string Name { get; set; }
public static bool UpdateSubject(Subject subject)
{
//Do something and return result
return true;
}
public bool UpdateSubject()
{
//Do something on 'this' and return result
return true;
}
}
Saya tahu saya akan mendapatkan banyak tendangan dari komunitas untuk pertanyaan yang sangat menjengkelkan ini, tetapi saya tidak bisa berhenti bertanya.
Apakah ini menjadi tidak praktis ketika berhadapan dengan warisan?
Pembaruan:
Ini terjadi di tempat kerja kami sekarang. Kami sedang mengerjakan aplikasi web asp.net 6 bulan dengan 5 pengembang. Arsitek kami memutuskan untuk menggunakan semua metode statis untuk semua API. Alasannya menjadi metode statis adalah ringan dan menguntungkan aplikasi web dengan menjaga server turun.
sumber
Jawaban:
Saya akan membahas masalah metode statis yang paling nyata dengan parameter "ini" eksplisit:
Anda kehilangan pengiriman virtual dan kemudian polimorfisme. Anda tidak pernah bisa menimpa metode itu di kelas turunan. Tentu saja Anda dapat mendeklarasikan metode
new
(static
) di kelas turunan, tetapi kode apa pun yang mengaksesnya harus mengetahui seluruh hierarki kelas dan melakukan pengecekan dan pengecoran secara eksplisit, yang persisnya harus dihindari oleh OO .Semacam ekstensi # 1, Anda tidak dapat mengganti instance kelas dengan antarmuka , karena antarmuka (dalam kebanyakan bahasa) tidak dapat mendeklarasikan
static
metode.Verbositas yang tidak perlu. Mana yang lebih mudah dibaca:
Subject.Update(subject)
atau adilsubject.Update()
?Pemeriksaan argumen. Sekali lagi tergantung pada bahasa, tetapi banyak yang akan mengkompilasi pemeriksaan implisit untuk memastikan bahwa
this
argumen tidaknull
untuk mencegah bug referensi nol dari menciptakan kondisi runtime yang tidak aman (semacam buffer overrun). Tidak menggunakan metode instan, Anda harus menambahkan centang ini secara eksplisit di awal setiap metode.Ini membingungkan. Ketika seorang programmer yang normal dan masuk akal melihat suatu
static
metode, ia secara alami akan berasumsi bahwa itu tidak memerlukan contoh yang valid (kecuali dibutuhkan beberapa contoh, seperti metode perbandingan atau kesetaraan, atau diharapkan dapat beroperasi padanull
referensi) . Melihat metode statis yang digunakan dengan cara ini akan membuat kita melakukan pengambilan ganda atau mungkin tiga kali lipat, dan setelah ke-4 atau ke-5 kita akan merasa stres dan marah dan tuhan membantu Anda jika kami tahu alamat rumah Anda.Ini bentuk duplikasi. Apa yang sebenarnya terjadi ketika Anda memanggil metode instance adalah bahwa kompiler atau runtime mencari metode dalam tabel metode tipe dan memanggilnya menggunakan
this
sebagai argumen. Anda pada dasarnya menerapkan kembali apa yang sudah dilakukan oleh kompiler. Anda melanggar KERING , mengulangi parameter yang sama berulang-ulang dalam metode yang berbeda saat itu tidak diperlukan.Sulit untuk memahami alasan bagus untuk mengganti metode instan dengan metode statis. Tolong jangan.
sumber
File
,FileInfo
danDirectoryInfo
(dan pada kenyataannya, ada perpustakaan yang menyembunyikan mereka di belakang antarmuka yang kemudian dapat disuntikkan sesuai kebutuhan dan dihina dalam tes).Anda sudah cukup banyak menggambarkan dengan tepat bagaimana Anda melakukan OOP di C, di mana hanya metode statis yang tersedia, dan "ini" adalah penunjuk struct. Dan ya, Anda dapat melakukan run time polymorphism di C dengan menentukan pointer fungsi selama konstruksi untuk disimpan sebagai salah satu elemen dari struct. Metode instan yang tersedia dalam bahasa lain hanyalah gula sintaksis yang pada dasarnya melakukan hal yang persis sama di bawah tenda. Beberapa bahasa, seperti python, berada di tengah-tengah, di mana parameter "diri" terdaftar secara eksplisit, tetapi sintaks khusus untuk memanggilnya menangani warisan dan polimorfisme untuk Anda.
sumber
obj->type->mthd(obj, ...);
dan itu hampir sama dengan apa yang terjadi dengan pengiriman virtual dalam bahasa lain (tetapi di belakang layar).Masalah dengan metode statis muncul saat Anda membutuhkan sub-kelas.
Metode statis tidak dapat ditimpa dalam sub-kelas, maka kelas baru Anda tidak dapat memberikan implementasi baru dari metode tersebut, membuatnya kurang berguna.
sumber
Jika Anda mendeklarasikan suatu metode
static
, Anda tidak harus membuat instance objek dari kelas (menggunakannew
kata kunci) untuk menjalankan metode tersebut. Namun, Anda tidak dapat merujuk ke variabel anggota apa pun kecuali mereka juga statis, dalam hal ini variabel anggota tersebut milik kelas, bukan objek instantiated khusus dari kelas.Dengan kata lain,
static
kata kunci menyebabkan deklarasi menjadi bagian dari definisi kelas, sehingga menjadi titik referensi tunggal di semua instance kelas (objek yang dipakai dari kelas).Ini mengikuti, kemudian, bahwa jika Anda ingin beberapa salinan berjalan dari kelas Anda, dan Anda tidak ingin negara (variabel anggota) untuk dibagikan di antara semua salinan berjalan Anda (yaitu setiap objek memegang keadaan uniknya sendiri), maka Anda tidak dapat mendeklarasikan variabel anggota itu statis.
Secara umum, Anda harus menggunakan
static
kelas dan metode hanya ketika Anda membuat metode utilitas yang menerima satu atau lebih parameter, dan mengembalikan objek semacam itu, tanpa efek samping (mis. Perubahan ke variabel keadaan di kelas)sumber
static
artinya, dia bertanya mengapa tidak hanya menyatakan semuanya statis.Subject
- tetapi sebagai parameter eksplisit, bukan implisitthis
parameter.this
parameter implisit . Ada perbedaan dalam harapan, tetapi di luar warisan, tidak ada perbedaan nyata dalam apa yang dapat Anda lakukan. Sebagai contoh, anggota non-statis dapat diakses - melalui parameter eksplisit.Alasan orang berpendapat bahwa 'metode statis menunjukkan desain buruk' belum tentu karena metode, itu sebenarnya data statis, implisit atau eksplisit. Secara implisit maksud saya SETIAP keadaan dalam program yang tidak terkandung dalam nilai atau parameter pengembalian. Mengubah keadaan dalam fungsi statis adalah kemunduran untuk pemrograman prosedural. Namun jika fungsi tidak mengubah keadaan, atau mendelegasikan modifikasi negara ke fungsi objek komponen, itu sebenarnya lebih merupakan paradigma fungsional daripada prosedural.
Jika Anda tidak mengubah status, metode dan kelas statis dapat memiliki banyak manfaat. Itu membuatnya jauh lebih mudah untuk memastikan metode murni, dan dengan demikian bebas dari efek samping dan kesalahan yang sepenuhnya dapat direproduksi. Ini juga memastikan bahwa berbagai metode dalam beberapa aplikasi menggunakan perpustakaan bersama dapat dipastikan mereka akan mendapatkan hasil yang sama dengan input yang sama, membuat pelacakan kesalahan dan pengujian unit menjadi lebih mudah.
Pada akhirnya tidak ada perbedaan dalam praktik antara objek berukuran besar yang biasa terlihat seperti 'StateManager' dan data statis atau global. Manfaat dari metode statis yang digunakan dengan benar adalah mereka dapat menunjukkan maksud penulis untuk tidak mengubah keadaan ke revisi nanti.
sumber
making ... unit testing much easier.
Tidak, tidak akan. Itu membuatnya membuat kode apa pun yang memanggil metode statis tidak mungkin untuk unit test, karena Anda tidak dapat mengisolasinya dari metode statis. Panggilan ke metode statis menjadi ketergantungan hardcoded ke kelas itu.Tergantung pada bahasa dan apa yang Anda coba lakukan, jawabannya mungkin tidak ada banyak perbedaan, tetapi
static
versi ini memiliki sedikit lebih banyak kekacauan.Seperti sintaksis contoh Anda menyarankan Java atau C #, saya pikir Thorbjørn Ravn Andersen benar untuk menunjukkan masalah utama (dengan keterlambatan mengikat). Dengan metode statis, tidak ada parameter "khusus" untuk pengikatan yang terlambat, jadi Anda tidak dapat memiliki pengikatan yang terlambat.
Akibatnya, metode statis hanyalah fungsi dalam modul, modul itu memiliki nama yang sama dengan kelas - itu sebenarnya bukan metode OOP sama sekali.
sumber
Anda pada dasarnya mengalahkan seluruh titik objek ketika Anda melakukan ini. Ada alasan bagus mengapa kita telah banyak bergeser dari kode prosedural ke kode berorientasi objek.
Saya tidak akan pernah mendeklarasikan metode statis yang menggunakan tipe kelas sebagai parameter. Itu hanya membuat kode lebih kompleks tanpa keuntungan.
sumber
object
kestatic
metode, dan kembali baruobject
. Pemrogram fungsional melakukan ini sepanjang waktu.Math
kelas statis "kompleks tanpa perolehan", atau apakah Anda lebih suka jika semua tipe angka memiliki metode virtual yang mendefinisikan nilai absolut, negasi, penambahan, kuadrat, akar sembarang, dan seterusnya? Saya kira tidak. objek rapi ketika Anda perlu menyimpan keadaan bisa berubah yang tersembunyi di mana Anda perlu menegakkan beberapa invarian. menumbuk bersama setiap metode yang dapat dipercaya yang beroperasi pada suatu tipe ke dalam tipe itu sendiri, ITULAH sesuatu yang mengarah pada kode yang kompleks dan tidak dapat dipertahankan. Saya setuju dengan Robert, Anda mungkin ingin melihat bagaimana programmer fungsional bekerja, itu bisa menjadi pembuka mata nyata!Ada banyak jawaban bagus di sini, dan mereka jauh lebih banyak wawasan dan pengetahuan daripada apa pun yang bisa saya berikan sebagai jawaban, tapi saya merasa ada sedikit sesuatu yang tidak ditekankan:
"Arsitek kami memutuskan untuk menggunakan semua metode statis untuk semua API. Alasannya karena metode statis itu ringan dan menguntungkan aplikasi web dengan menjaga server memuat ."
(Penekanan berani adalah milikku)
2c saya pada bagian pertanyaan ini adalah ini:
Secara teoritis, apa yang dikatakan benar ada: memanggil metode statis hanya memiliki overhead sebenarnya memanggil metode itu. Memanggil metode non-statis (instance) memiliki overhead tambahan pertama instantiating objek, dan pada beberapa titik, menghancurkan instance (baik secara manual atau melalui beberapa bentuk pengumpulan sampah otomatis, tergantung pada platform yang digunakan).
Drama ini sedikit menganjurkan setan: kita bisa melangkah lebih jauh dan mengatakan hal-hal seperti:
ini bisa menjadi sangat buruk jika sebuah instance dibuat untuk setiap pemanggilan metode (instance) (bukan hanya membiarkannya statis dan memanggilnya seperti itu)
tergantung dari kerumitan konstruktor, tipe hirarki, anggota contoh lain dan faktor tidak dikenal lainnya, overhead tambahan dari pemanggilan metode non-statis dapat bervariasi dan menjadi sangat besar
Sebenarnya, IMHO, poin-poin di atas (dan pendekatan umum "mari kita gunakan statika karena mereka lebih cepat") adalah argumen manusia jerami / penilaian:
jika kodenya bagus, dan, lebih spesifik pada argumen ini, jika instans dibuat hanya jika perlu (dan dihancurkan dengan cara yang optimal), maka Anda tidak mendapatkan overhead tambahan dari menggunakan metode insance jika diperlukan (karena jika Anda hanya membuat objek yang diperlukan, itu akan dibuat bahkan jika metode itu dinyatakan statis di mana lagi = overhead instanciation yang sama)
dengan menyalahgunakan deklarasi metode statis dengan cara ini, dimungkinkan untuk menyembunyikan beberapa masalah dengan kode Anda sehubungan dengan bagaimana instance dibuat (karena metode ini statis, kode instanciation yang salah dapat dilewatkan tanpa diketahui sampai nanti, dan itu tidak pernah baik).
sumber
Ini adalah pertanyaan yang sangat menarik yang cenderung memiliki jawaban yang sangat berbeda tergantung pada komunitas yang Anda tanyakan. Jawaban lain tampaknya bias C # atau java: bahasa pemrograman yang (sebagian besar) berorientasi objek murni dan memiliki semacam pandangan idiomatis tentang apa orientasi objek.
Di komunitas lain, seperti C ++, orientasi objek ditafsirkan dengan lebih bebas. Beberapa ahli yang sudah mengetahui telah mempelajari subjek dan, sebenarnya, menyimpulkan bahwa fungsi bebas meningkatkan enkapsulasi (penekanan adalah milikku):
Bagi mereka yang tidak terbiasa dengan terminologi C ++:
Sekarang, untuk menjawab pertanyaan Anda:
Tidak, Anda tidak harus selalu menggunakan metode statis.
Tapi, Anda harus menggunakannya kapan pun Anda hanya perlu menggunakan API publik dari suatu kelas.
sumber
di Jawa ...
Metode statis tidak ditimpa tetapi disembunyikan sebagai gantinya dan itu akan menjadi perbedaan besar (masalah?) Dalam kasus memperluas kelas.
Di sisi lain saya perhatikan bahwa programmer Java memiliki kecenderungan untuk berpikir bahwa semua HARUS menjadi objek, tanpa benar-benar mengerti mengapa, dan saya tidak setuju.
Statis harus digunakan untuk kode khusus untuk kelas. Statis tidak bekerja dengan baik dengan warisan.
beberapa contoh penggunaan metode statis yang baik adalah fungsi independen tanpa efek samping.
juga melihat kata kunci disinkronkan ...
sumber