Saya tidak berpikir ada jawaban bahasa-agnostik untuk ini karena apa yang merupakan "properti" adalah pertanyaan khusus-bahasa, dan apa yang diharapkan penelepon dari "properti" adalah pertanyaan khusus bahasa. Saya pikir cara yang paling bermanfaat untuk memikirkan hal ini adalah dengan memikirkan seperti apa penampilannya dari sudut pandang si penelepon.
Dalam C #, properti berbeda karena sifatnya (secara konvensional) dikapitalisasi (seperti metode) tetapi tidak memiliki tanda kurung (seperti variabel instance publik). Jika Anda melihat kode berikut, tidak ada dokumentasi, apa yang Anda harapkan?
var reciprocalHeading = myHeading.Reciprocal;
Sebagai pemula C #, tetapi orang yang membaca Panduan Penggunaan Properti Microsoft , saya berharap Reciprocal
, antara lain:
- menjadi anggota data logis dari
Heading
kelas
- murah untuk menelepon, sehingga tidak perlu bagi saya untuk men-cache nilai
- tidak memiliki efek samping yang dapat diamati
- menghasilkan hasil yang sama jika dipanggil dua kali berturut-turut
- (mungkin) menawarkan
ReciprocalChanged
acara
Dari asumsi-asumsi ini, (3) dan (4) mungkin benar (dengan asumsi Heading
adalah tipe nilai yang tidak berubah, seperti dalam jawaban Ewan ), (1) dapat diperdebatkan, (2) tidak diketahui tetapi juga dapat diperdebatkan, dan (5) tidak mungkin untuk masuk akal semantik (meskipun apa pun yang memiliki tajuk mungkin harus memiliki HeadingChanged
acara). Ini menunjukkan kepada saya bahwa dalam C # API, "dapatkan atau hitung timbal balik" tidak boleh diimplementasikan sebagai properti, tetapi terutama jika perhitungannya murah dan Heading
tidak dapat diubah, ini merupakan kasus batas.
(Namun, perlu diketahui bahwa tidak ada satu pun dari kekhawatiran ini yang ada hubungannya dengan apakah memanggil properti menciptakan contoh baru , bahkan tidak (2). Membuat objek di CLR, dengan sendirinya, cukup murah.)
Di Jawa, properti adalah konvensi penamaan metode. Jika saya melihat
Heading reciprocalHeading = myHeading.getReciprocal();
harapan saya mirip dengan yang di atas (jika tidak secara eksplisit ditetapkan): Saya berharap panggilan menjadi murah, idempoten, dan kurang dalam efek samping. Namun, di luar kerangka JavaBeans konsep "properti" tidak terlalu berarti di Jawa, dan terutama ketika mempertimbangkan properti yang tidak dapat diubah tanpa korespondensi setReciprocal()
, getXXX()
konvensi ini sekarang agak kuno. Dari Effective Java , edisi kedua (sudah lebih dari delapan tahun sekarang):
Metode yang mengembalikan non- boolean
fungsi atau atribut objek di mana mereka dipanggil biasanya dinamai dengan kata benda, frase kata benda, atau frase kata kerja yang dimulai dengan kata kerja get
…. Ada kontingen vokal yang mengklaim bahwa hanya bentuk ketiga (dimulai dengan get
) yang dapat diterima, tetapi ada sedikit dasar untuk klaim ini. Dua bentuk pertama biasanya mengarah pada kode yang lebih mudah dibaca ... (hlm. 239)
Dalam API kontemporer dan lebih lancar, saya berharap bisa melihatnya
Heading reciprocalHeading = myHeading.reciprocal();
- yang sekali lagi akan menyarankan bahwa panggilan itu murah, idempoten, dan tidak memiliki efek samping, tetapi tidak akan mengatakan apa-apa tentang apakah perhitungan baru dilakukan atau objek baru dibuat. Ini baik; dalam API yang baik, saya seharusnya tidak peduli.
Di Ruby, tidak ada yang namanya properti. Ada "atribut", tetapi jika saya melihat
reciprocalHeading = my_heading.reciprocal
Saya tidak memiliki cara langsung untuk mengetahui apakah saya mengakses variabel instan @reciprocal
melalui attr_reader
metode accessor sederhana, atau apakah saya memanggil metode yang melakukan perhitungan mahal. Fakta bahwa nama metode adalah kata benda sederhana, meskipun, daripada mengatakan calcReciprocal
, menyarankan, sekali lagi, bahwa panggilan itu setidaknya murah dan mungkin tidak memiliki efek samping.
Dalam Scala, konvensi penamaan adalah bahwa metode dengan efek samping mengambil kurung dan metode tanpa mereka tidak, tetapi
val reciprocal = heading.reciprocal
dapat berupa:
// immutable public value initialized at creation time
val reciprocal: Heading = …
// immutable public value initialized on first use
lazy val reciprocal: Heading = …
// public method, probably recalculating on each invocation
def reciprocal: Heading = …
// as above, with parentheses that, by convention, the caller
// should only omit if they know the method has no side effects
def reciprocal(): Heading = …
(Perhatikan bahwa Scala memungkinkan berbagai hal yang tetap tidak disarankan oleh panduan gaya . Ini adalah salah satu gangguan utama saya pada Scala.)
Kurangnya tanda kurung memberi tahu saya bahwa panggilan itu tidak memiliki efek samping; namanya, sekali lagi, menunjukkan bahwa panggilan itu harus relatif murah. Di luar itu, saya tidak peduli bagaimana hal itu memberi saya nilai.
Singkatnya: Ketahui bahasa yang Anda gunakan, dan tahu apa harapan yang akan dibawa oleh programmer lain ke API Anda. Yang lainnya adalah detail implementasi.
Heading
sebagai tipe yang tidak berubah danreciprocal
mengembalikan yang baruHeading
adalah "lubang keberhasilan" praktik yang baik. (dengan peringatan di kedua panggilan untukreciprocal
harus mengembalikan "hal yang sama", yaitu mereka harus lulus ujian kesetaraan.)