Bagaimana pendekatan menciptakan metode kelas privat ini bekerja:
class Person
def self.get_name
persons_name
end
class << self
private
def persons_name
"Sam"
end
end
end
puts "Hey, " + Person.get_name
puts "Hey, " + Person.persons_name #=> raises "private method `persons_name' called for Person:Class (NoMethodError)"
Tetapi ini tidak:
class Person
def self.get_name
persons_name
end
private
def self.persons_name
"Sam"
end
end
puts "Hey, " + Person.get_name
puts "Hey, " + Person.persons_name
ruby
access-specifier
99 mil
sumber
sumber
Jawaban:
private
tampaknya tidak berfungsi jika Anda mendefinisikan metode pada objek eksplisit (dalam kasus Andaself
). Anda dapat menggunakanprivate_class_method
untuk mendefinisikan metode kelas sebagai pribadi (atau seperti yang Anda jelaskan).Atau (dalam ruby 2.1+), karena definisi metode mengembalikan simbol nama metode, Anda juga dapat menggunakan ini sebagai berikut:
sumber
ExiRe menulis:
Membingungkan mungkin, membuat frustrasi mungkin, tetapi menjijikkan itu pasti tidak.
Itu masuk akal setelah Anda memahami model obyek Ruby dan sesuai metode pencarian mengalir , terutama ketika mempertimbangkan bahwa
private
adalah TIDAK pengubah akses / visibilitas, namun sebenarnya metode panggilan (dengan kelas sebagai penerima nya) seperti yang dibahas di sini ... tidak ada yang namanya "bagian pribadi" di Ruby.Untuk mendefinisikan metode instance privat , Anda memanggil
private
kelas instance untuk mengatur visibilitas default untuk metode yang didefinisikan selanjutnya menjadi privat ... dan karenanya masuk akal untuk mendefinisikan metode kelas privat dengan memanggilprivate
kelas class, yaitu. metaclass-nya.Bahasa OO arus utama yang diproklamirkan sendiri dapat memberikan Anda sintaks yang kurang membingungkan, tetapi Anda pasti menukarnya dengan model objek yang membingungkan dan kurang konsisten (tidak konsisten?) Tanpa kekuatan fasilitas pemrograman metaprogram Ruby.
sumber
private_class_method :method_name
yang bisa Anda lakukanprivate_class_method def method_name...
.send(private_method)
juga dapat diakses di luar objek.private_class_method def self.method_name
Secara default semua metode kelas adalah publik. Untuk menjadikannya pribadi, Anda dapat menggunakan Module # private_class_method seperti @tjwallace menulis atau mendefinisikannya secara berbeda, seperti yang Anda lakukan:
class << self
membuka kelas singleton diri, sehingga metode dapat didefinisikan ulang untuk objek diri saat ini. Ini digunakan untuk mendefinisikan metode kelas / modul ("statis"). Hanya di sana, mendefinisikan metode pribadi benar-benar memberi Anda metode kelas pribadi.sumber
Hanya untuk kelengkapannya, kita juga dapat menghindari mendeklarasikan private_class_method dalam baris terpisah. Saya pribadi tidak suka penggunaan ini tetapi senang mengetahui bahwa itu ada.
sumber
Saya juga menemukan Ruby (atau setidak-tidaknya sepengetahuan saya) singkat dari tanda di area ini. Sebagai contoh, berikut ini melakukan apa yang saya inginkan tetapi canggung,
Masalah saya dengan kode di atas adalah bahwa persyaratan sintaksis Ruby dan metrik kualitas kode saya berkonspirasi untuk dibuat untuk kode rumit. Agar kode berfungsi baik seperti yang saya inginkan dan untuk menenangkan metrik, saya harus membandingkan () metode kelas. Karena saya tidak ingin itu menjadi bagian dari API publik kelas, saya ingin itu menjadi pribadi, namun 'pribadi' dengan sendirinya tidak berfungsi. Alih-alih saya terpaksa menggunakan 'private_class_method' atau beberapa solusi semacam itu. Ini, pada gilirannya, memaksa penggunaan 'self.class.send (: bandingkan ...' untuk setiap variabel yang saya uji di '== ()'. Sekarang agak sulit.
sumber
Metode instance didefinisikan di dalam blok definisi kelas. Metode kelas didefinisikan sebagai metode singleton pada kelas singleton suatu kelas, juga secara informal dikenal sebagai "metaclass" atau "eigenclass".
private
bukan kata kunci, tetapi metode ( Modul # pribadi ).Ini adalah panggilan ke metode
self#private
/A#private
yang "mengaktifkan" akses pribadi untuk semua definisi metode instance yang akan datang hingga beralih sebaliknya:Seperti disebutkan sebelumnya, metode kelas benar-benar metode tunggal yang didefinisikan pada kelas tunggal.
Atau menggunakan sintaks khusus untuk membuka tubuh definisi dari kelas A anonim, tunggal:
Penerima "pesan pribadi" - diri di dalam
class A
adalah objek kelas A. diri di dalamclass << A
blok adalah objek lain, kelas singleton.Contoh berikut ini pada kenyataannya memanggil dua metode berbeda yang disebut pribadi , menggunakan dua penerima atau target yang berbeda untuk panggilan tersebut. Pada bagian pertama, kita mendefinisikan metode instance privat ("pada kelas A"), pada yang kedua kita mendefinisikan metode kelas privat (sebenarnya metode singleton pada objek kelas singleton dari A).
Sekarang, tulis ulang contoh ini sedikit:
Bisakah Anda melihat kesalahan [yang dilakukan desainer bahasa Ruby]? Anda beralih pada akses pribadi untuk semua metode instance A yang akan datang, tetapi lanjutkan untuk mendeklarasikan metode singleton pada kelas yang berbeda, kelas singleton.
sumber
Ruby tampaknya memberikan solusi yang buruk. Untuk menjelaskan, mulailah dengan contoh C ++ sederhana yang memperlihatkan akses ke metode kelas privat:
Menjalankan di atas
Sekarang Ruby tampaknya tidak memberikan yang setara. Menurut saya, aturan Ruby adalah bahwa metode pribadi tidak boleh diakses dengan penerima. Itu adalah,
Tidak masalah untuk metode instance pribadi, tetapi menyebabkan masalah dengan metode kelas privat.
Saya ingin Ruby berfungsi dengan cara ini:
Tapi, sayangnya, hal di atas tidak berhasil. Apakah ada yang tahu cara yang lebih baik?
Ketika saya melihat 'kirim' sebelum suatu metode, itu adalah tanda yang jelas bahwa kode tersebut melanggar maksud perancang API, tetapi dalam hal ini desainnya secara khusus memiliki metode instance dari panggilan kelas metode kelas privat.
sumber
Pada ruby 2.3.0
sumber
private def self.second_method
sebelum masing-masing metode notasi, yang tidak bekerja pada batu delima saya 2.3.3. Tetapi notasi ini bekerja untuk saya.Check.second_method
juga berfungsi tanpa masalah, jadi itu tidak benar-benar pribadi.private_class_method :second_method