Ruby memiliki ini berguna dan nyaman untuk berbagi contoh variabel dengan menggunakan tombol suka
attr_accessor :var
attr_reader :var
attr_writer :var
Mengapa saya memilih attr_reader
atau attr_writer
jika saya hanya bisa menggunakan attr_accessor
? Apakah ada sesuatu seperti kinerja (yang saya ragu)? Saya kira ada alasan, kalau tidak mereka tidak't telah membuat kunci tersebut.
Anda dapat menggunakan berbagai accesor untuk menyampaikan maksud anda dengan seseorang yang membaca kode anda, dan membuatnya lebih mudah untuk menulis kelas yang akan bekerja dengan benar tidak peduli bagaimana mereka API umum disebut.
class Person
attr_accessor :age
...
end
Di sini, saya dapat melihat bahwa saya dapat membaca dan menulis usia.
class Person
attr_reader :age
...
end
Di sini, saya dapat melihat bahwa saya hanya dapat membaca usia. Bayangkan bahwa itu diatur oleh konstruktor dari kelas ini dan setelah itu tetap konstan. Jika ada mutator (penulis) untuk usia dan kelas yang ditulis dengan asumsi bahwa usia, setelah ditetapkan, tidak berubah, maka bug yang dapat hasil dari kode panggilan yang mutator.
Tapi apa yang terjadi di balik layar?
Jika anda menulis:
attr_writer :age
Yang akan diterjemahkan menjadi:
def age=(value)
@age = value
end
Jika anda menulis:
attr_reader :age
Yang akan diterjemahkan menjadi:
def age
@age
end
Jika anda menulis:
attr_accessor :age
Yang akan diterjemahkan menjadi:
def age=(value)
@age = value
end
def age
@age
end
Mengetahui bahwa, di sini's cara lain untuk berpikir tentang hal ini: Jika anda tidak memiliki attr_... pembantu, dan harus menulis accesor diri anda, anda akan menulis lagi accesor dari kelas anda dibutuhkan? Misalnya, jika usia hanya diperlukan untuk bisa membaca, apakah anda juga menulis sebuah metode yang memungkinkan untuk ditulis?
Semua jawaban diatas adalah benar; attr_reader
dan attr_writer
lebih nyaman untuk menulis dari manual mengetik metode mereka shorthands untuk. Selain itu mereka menawarkan kinerja yang jauh lebih baik dari penulisan metode definisi sendiri. Untuk info lebih lanjut lihat slide 152 seterusnya dari talk (PDF) oleh Harun Patterson.
Tidak semua atribut dari sebuah objek yang dimaksudkan untuk langsung diatur dari luar kelas. Setelah penulis untuk semua instance variable pada umumnya tanda lemah enkapsulasi dan peringatan bahwa anda're memperkenalkan terlalu banyak coupling antara kelas anda.
Sebagai contoh praktis: aku menulis sebuah desain program di mana anda menempatkan barang-barang di dalam kontainer. Item telah attr_reader :container
, tapi itu tak't masuk akal untuk menawarkan seorang penulis, karena hanya waktu yang item's kontainer harus berubah adalah ketika itu's ditempatkan di tempat yang baru, yang juga memerlukan informasi posisi.
Anda don't selalu ingin anda contoh variabel-variabel yang akan sepenuhnya dapat diakses dari luar kelas. Ada banyak kasus di mana yang memungkinkan akses baca ke instance variabel akal, tapi menulis itu tidak mungkin (misalnya model yang akan mengambil data dari baca-satunya sumber). Ada kasus di mana anda ingin sebaliknya, tapi aku bisa't pikir apa yang kau't dibikin dari atas kepala saya.
Hal ini penting untuk memahami bahwa accesor membatasi akses ke variabel, tetapi bukan konten mereka. Di ruby, seperti di beberapa OO bahasa, setiap variabel adalah pointer ke sebuah instance. Jadi jika anda memiliki atribut untuk sebuah Hash, misalnya, dan anda mengatur untuk menjadi "baca hanya" anda selalu dapat mengubah isinya, tapi bukan isi dari pointer. Lihat ini:
irb(main):024:0> class A
irb(main):025:1> attr_reader :a
irb(main):026:1> def initialize
irb(main):027:2> @a = {a:1, b:2}
irb(main):028:2> end
irb(main):029:1> end
=> :initialize
irb(main):030:0> a = A.new
=> #<A:0x007ffc5a10fe88 @a={:a=>1, :b=>2}>
irb(main):031:0> a.a
=> {:a=>1, :b=>2}
irb(main):032:0> a.a.delete(:b)
=> 2
irb(main):033:0> a.a
=> {:a=>1}
irb(main):034:0> a.a = {}
NoMethodError: undefined method `a=' for #<A:0x007ffc5a10fe88 @a={:a=>1}>
from (irb):34
from /usr/local/bin/irb:11:in `<main>'
Seperti yang anda lihat mungkin menghapus pasangan kunci/nilai dari Hash @a, seperti menambahkan tombol baru, perubahan nilai-nilai, eccetera. Tapi anda bisa't arahkan ke objek baru karena ini hanya membaca contoh variabel.