Apakah attr_accessor bekerja dengan cara yang sama di Git? Saya menemukan bahwa beberapa tutorial tidak cukup menjelaskan dan yang lain menganggap pengetahuan sebelumnya.
Angelfirenze
10
@Angelfirenze, gittidak ada hubungannya dengan attr_accessor. Git adalah software kontrol versi, sedangkan attr_accessoradalah metode di Ruby .
Uzbekjon
Jawaban:
2360
Katakanlah Anda memiliki kelas Person.
classPersonend
person =Person.new
person.name # => no method error
Jelas kami tidak pernah mendefinisikan metode name. Ayo lakukan itu.
classPersondef name
@name# simply returning an instance variable @nameendend
person =Person.new
person.name # => nil
person.name ="Dennis"# => no method error
Aha, kita dapat membaca namanya, tetapi itu tidak berarti kita dapat menetapkan namanya. Itu adalah dua metode yang berbeda. Yang pertama disebut pembaca dan yang terakhir disebut penulis . Kami belum membuat penulis, jadi mari kita lakukan.
classPersondef name
@nameenddef name=(str)@name= str
endend
person =Person.new
person.name ='Dennis'
person.name # => "Dennis"
Luar biasa. Sekarang kita dapat menulis dan membaca variabel instan @namemenggunakan metode pembaca dan penulis. Kecuali, ini sering dilakukan, mengapa buang waktu menulis metode ini setiap waktu? Kita bisa melakukannya dengan lebih mudah.
classPerson
attr_reader :name
attr_writer :name
end
Bahkan ini bisa berulang. Bila Anda ingin pembaca dan penulis gunakan saja accessor!
classPerson
attr_accessor :name
end
person =Person.new
person.name ="Dennis"
person.name # => "Dennis"
Bekerja dengan cara yang sama! Dan coba tebak: variabel instan @namedi objek orang kita akan diatur seperti ketika kita melakukannya secara manual, sehingga Anda dapat menggunakannya dalam metode lain.
Itu dia. Untuk memahami bagaimana attr_reader,, attr_writerdan attr_accessormetode sebenarnya menghasilkan metode untuk Anda, baca jawaban lain, buku, dokumen ruby.
@akunin - terima kasih atas jawaban yang jelas itu. Apa yang hilang bagi saya adalah mengapa sintaksis Ruby menyarankan tanda titik dua ':' untuk variabel instan dalam pernyataan attr_ *? Tampaknya akan lebih mudah untuk menggunakan sintaks '@' yang sama yang digunakan di tempat lain di kelas untuk merujuk ke variabel.
Will
207
@ WilliamSmith Untuk menjawab pertanyaan Anda, Anda perlu memahami bahwa attr_accessorini adalah metode yang dipanggil pada kelas saat ini, dan :namemerupakan parameter yang Anda berikan ke metode itu. Ini bukan sintaks khusus, ini metode panggilan yang sederhana. Jika Anda memberikannya @namevariabel, itu tidak masuk akal, karena @name akan berisi nil. Jadi itu seperti menulis attr_accessor nil. Anda tidak meneruskannya variabel yang perlu dibuat, Anda meneruskan nama yang Anda inginkan variabel dipanggil.
Max Chernyak
23
@akunin - Itu masuk akal. Saya baru hari ini telah belajar bahwa ruby sebenarnya 'berjalan' karena diurai melalui file dan bahwa setiap pernyataan dan ekspresi sebenarnya adalah panggilan metode pada beberapa objek. Termasuk attr_accessor. Sangat membantu.
Will
52
menggunakan Rails selama 3 tahun, bahkan tidak pernah tahu ini. Malu
Sean Xiao
5
@ Buminda ya, tetapi metode namedan variabel @namebukan hal yang sama. Jangan membingungkan mereka. Anda memiliki variabel instan @namedi kelas Anda, dan Anda menentukan attr_reader :nameuntuk dapat membacanya dari luar. Tanpa attr_readertidak ada cara sederhana yang dapat Anda akses di @nameluar kelas Anda.
Max Chernyak
127
attr_accessor adalah hanya sebuah metode . (Tautan harus memberikan wawasan lebih banyak tentang cara kerjanya - lihat pasangan metode yang dihasilkan, dan tutorial akan menunjukkan kepada Anda bagaimana menggunakannya.)
Kuncinya adalah bahwa classitu bukan definisi di Ruby (itu adalah "hanya definisi" dalam bahasa seperti C ++ dan Java), tetapi itu adalah ekspresi yang mengevaluasi . Selama evaluasi ini ketika attr_accessormetode dipanggil yang pada gilirannya memodifikasi kelas saat ini - ingat penerima implisit:, di self.attr_accessormanaself objek kelas "terbuka" pada titik ini.
Kebutuhan attr_accessordan teman, adalah, yah:
Ruby, seperti Smalltalk, tidak mengizinkan variabel instan diakses di luar metode 1 untuk objek itu. Yaitu, variabel instance tidak dapat diakses dalam x.ybentuk seperti yang umum di katakan, Java atau bahkan Python. Dalam Ruby yselalu diambil sebagai pesan untuk mengirim (atau "metode untuk memanggil"). Dengan demikian attr_*metode membuat pembungkus yang proksi @variableakses instance melalui metode yang dibuat secara dinamis.
Boilerplate menyebalkan
Semoga ini menjelaskan beberapa detail kecil. Selamat coding.
1 Ini tidak sepenuhnya benar dan ada beberapa "teknik" di sekitar ini , tetapi tidak ada dukungan sintaks untuk akses "variabel instance publik".
Ketika Anda mengatakan attr_accessor adalah "hanya metode" saya mengerti. Tetapi apakah sintaks yang digunakan untuk memanggil metode itu disebut? Saya mengalami kesulitan menemukan bagian dalam dokumentasi ruby yang berbicara tentang sintaksis seperti some_method: name => "whatever",: notherName,: etc
BT
68
attr_accessoradalah (seperti yang dinyatakan @pst) hanya sebuah metode. Apa yang dilakukannya adalah menciptakan lebih banyak metode untuk Anda.
Jadi kode ini di sini:
classFoo
attr_accessor :bar
end
setara dengan kode ini:
classFoodef bar
@barenddef bar=( new_value )@bar= new_value
endend
Anda dapat menulis metode semacam ini sendiri di Ruby:
classModuledef var( method_name )
inst_variable_name ="@#{method_name}".to_sym
define_method method_name do
instance_variable_get inst_variable_name
end
define_method "#{method_name}="do|new_value|
instance_variable_set inst_variable_name, new_value
endendendclassFoo
var :bar
end
f =Foo.new
p f.bar #=> nil
f.bar =42
p f.bar #=> 42
Ini adalah contoh yang bagus di mana metaprogramming digunakan bahkan dalam skenario tingkat pemula. Sangat bagus.
John Simon
2
Saya sedang mencari sketsa implementasi attr_accessordan akhirnya ditemukan di sini! Meskipun ini menyelesaikan masalah saya, tetapi saya ingin tahu di mana (buku / dokumen resmi) dapatkah saya menemukan contoh implementasi seperti ini?
Wasif Hossain
40
attr_accessor sangat sederhana:
attr_accessor :foo
adalah jalan pintas untuk:
def foo=(val)@foo= val
enddef foo
@fooend
itu tidak lebih dari pengambil / penyetel untuk suatu objek
jawaban anda baik-baik saja. 'Pintasan' berarti "rute alternatif yang lebih pendek" menurut kamus saya, bukan "sintaksis gula" atau "makro yang ditafsirkan oleh penerjemah".
bowsersenior
25
Pada dasarnya mereka memalsukan atribut data yang dapat diakses publik, yang tidak dimiliki Ruby.
Meskipun komentar ini tidak sepenuhnya berguna, itu benar. Menyoroti fakta bahwa atribut data publik tidak ada di luar metode "dapatkan" di Ruby, yang merupakan info yang sangat berguna bagi seseorang yang mencoba mempelajari bahasa tersebut.
Eric Dand
3
Ini seharusnya tidak diturunkan. Sebagai orang non-Ruby yang mencoba memecahkan masalah ini, jawaban ini sangat membantu!
Brad
1
Setuju, tampaknya sangat mirip dengan nama C # {get; set;}
David Miler
17
Ini hanya metode yang mendefinisikan metode pengambil dan penyetel untuk variabel instan. Contoh implementasi adalah:
defself.attr_accessor(*names)
names.each do|name|
define_method(name){instance_variable_get("@#{name}")}# This is the getter
define_method("#{name}="){|arg| instance_variable_set("@#{name}", arg)}# This is the setterendend
Ini adalah cuplikan kode yang sangat membantu untuk menyelesaikan pertanyaan lain yang saya miliki terkait dengan metaprogramming.
alexventuraio
15
Penjelasan Sederhana Tanpa Kode Apa Pun
Sebagian besar jawaban di atas menggunakan kode. Penjelasan ini mencoba menjawabnya tanpa menggunakan apa pun, melalui analogi / cerita:
Pihak luar tidak dapat mengakses rahasia internal CIA
Mari kita bayangkan tempat yang sangat rahasia: CIA. Tidak ada yang tahu apa yang terjadi di CIA selain dari orang-orang di dalam CIA. Dengan kata lain, orang eksternal tidak dapat mengakses informasi apa pun di CIA. Tetapi karena tidak ada gunanya memiliki organisasi yang sepenuhnya rahasia, informasi tertentu tersedia untuk dunia luar - hanya hal-hal yang CIA ingin semua orang tahu tentang tentu saja: misalnya Direktur CIA, bagaimana ramah lingkungan departemen ini dibandingkan kepada semua departemen pemerintah lainnya, dll. Informasi lain: mis. siapa yang merupakan agen rahasia di Irak atau Afghanistan - hal-hal semacam ini mungkin akan tetap menjadi rahasia selama 150 tahun ke depan.
Jika Anda berada di luar CIA, Anda hanya dapat mengakses informasi yang telah disediakan untuk publik. Atau untuk menggunakan bahasa CIA Anda hanya dapat mengakses informasi yang "dihapus".
Informasi yang ingin disediakan CIA untuk masyarakat umum di luar CIA disebut: atribut.
Arti dari atribut baca dan tulis:
Dalam kasus CIA, sebagian besar atribut adalah "hanya baca". Ini berarti jika Anda adalah pihak di luar CIA, Anda dapat bertanya: "siapa direktur CIA?" dan Anda akan mendapatkan jawaban langsung. Tetapi yang tidak bisa Anda lakukan dengan atribut "read only" adalah membuat perubahan pada CIA. mis. Anda tidak dapat membuat panggilan telepon dan tiba-tiba memutuskan bahwa Anda ingin Kim Kardashian menjadi Direktur, atau Anda ingin Paris Hilton menjadi Panglima Tertinggi.
Jika atribut memberi Anda akses "tulis", maka Anda dapat membuat perubahan jika Anda ingin, bahkan jika Anda berada di luar. Jika tidak, satu-satunya hal yang dapat Anda lakukan adalah membaca.
Dengan kata lain, pengakses memungkinkan Anda untuk membuat pertanyaan, atau membuat perubahan, ke organisasi yang sebaliknya tidak membiarkan orang luar masuk, tergantung pada apakah pengakses membaca atau menulis pengakses.
Objek di dalam kelas dapat dengan mudah mengakses satu sama lain
Di sisi lain, jika Anda sudah berada di dalam CIA, maka Anda dapat dengan mudah memanggil operator CIA Anda di Kabul karena informasi ini mudah diakses mengingat Anda sudah berada di dalam. Tetapi jika Anda berada di luar CIA, Anda tidak akan diberikan akses: Anda tidak akan dapat mengetahui siapa mereka (akses baca), dan Anda tidak akan dapat mengubah misi mereka (akses tulis).
Persis sama dengan kelas dan kemampuan Anda untuk mengakses variabel, properti, dan metode di dalamnya. HTH! Ada pertanyaan, silakan tanyakan dan saya harap saya bisa mengklarifikasi.
Penjelasan Anda masuk akal! +1 Maaf, apakah Anda yakin ungkapan "informasi yang dihapus oleh CIA benar?
kouty
ada berbagai tingkat "izin" di CIA: mis. Top Secret (tidak ada yang lain kecuali Prez), atau kepercayaan publik (semua orang bisa membaca info itu). CIA sebenarnya menyediakan banyak fakta yang sangat keren!
BKSpurgeon
Anda pantas mendapatkan suara positif hanya untuk Kardashian, Paris Hilton contoh :) Saya pikir itu cukup buruk dengan Trump untuk Presiden, bayangkan dua yang bertanggung jawab omg!
rmcsharry
Iya! Itulah yang kami butuhkan, StackOverflow tanpa kode! :-)
Marvin
13
Jika Anda terbiasa dengan konsep OOP, Anda harus terbiasa dengan metode pengambil dan penyetel. attr_accessor melakukan hal yang sama di Ruby.
Getter dan Setter secara Umum
classPersondef name
@nameenddef name=(str)@name= str
endend
person =Person.new
person.name ='Eshaan'
person.name # => "Eshaan"
Metode Setter
def name=(val)@name= val
end
Metode pengambil
def name
@nameend
Metode Getter dan Setter di Ruby
classPerson
attr_accessor :name
end
person =Person.new
person.name ="Eshaan"
person.name # => "Eshaan"
penjelasan sempurna! Ini adalah perilaku yang sangat berguna dan dapat diganti dengan sangat mudah.
Rubyrider
12
Saya juga menghadapi masalah ini dan menulis jawaban yang agak panjang untuk pertanyaan ini. Sudah ada beberapa jawaban bagus untuk ini, tetapi siapa pun yang mencari klarifikasi lebih lanjut, saya harap jawaban saya dapat membantu
Inisialisasi Metode
Initialize memungkinkan Anda untuk mengatur data ke instance objek saat membuat instance daripada harus mengaturnya pada baris terpisah dalam kode Anda setiap kali Anda membuat instance baru dari kelas.
classPersondef initialize(name)@name= name
enddef greeting
"Hello #{@name}"endend
person =Person.new("Denis")
puts person.greeting
Dalam kode di atas kita menetapkan nama "Denis" menggunakan metode inisialisasi dengan melewati Dennis melalui parameter di Inisialisasi. Jika kami ingin menetapkan nama tanpa metode inisialisasi kami dapat melakukannya seperti ini:
Dalam kode di atas, kita menetapkan nama dengan memanggil metode setter attr_accessor menggunakan person.name, daripada mengatur nilai saat inisialisasi objek.
Kedua "metode" dalam melakukan pekerjaan ini, tetapi menginisialisasi menghemat waktu dan baris kode.
Ini adalah satu-satunya tugas menginisialisasi. Anda tidak dapat memanggil inisialisasi sebagai metode. Untuk benar-benar mendapatkan nilai-nilai objek instan Anda perlu menggunakan getter dan setter (attr_reader (get), attr_writer (set), dan attr_accessor (keduanya)). Lihat di bawah untuk detail lebih lanjut tentang itu.
Getters, attr_reader: Seluruh tujuan pengambil adalah untuk mengembalikan nilai variabel instance tertentu. Kunjungi kode contoh di bawah ini untuk rinciannya.
Dalam kode di atas Anda memanggil metode "item_name" dan "kuantitas" pada contoh Item "example". "Menempatkan example.item_name" dan "example.quantity" akan mengembalikan (atau "get") nilai untuk parameter yang diteruskan ke dalam "example" dan menampilkannya ke layar.
Untungnya di Ruby ada metode inheren yang memungkinkan kita untuk menulis kode ini secara lebih ringkas; metode attr_reader. Lihat kode di bawah ini;
Sintaks ini bekerja dengan cara yang persis sama, hanya saja itu menyelamatkan kita enam baris kode. Bayangkan jika Anda memiliki 5 status yang lebih disebabkan oleh kelas Item? Kode akan lama cepat.
Setter, attr_writer: Apa yang membuat saya bingung pada awalnya dengan metode setter adalah bahwa di mata saya tampaknya melakukan fungsi yang identik dengan metode inisialisasi. Di bawah ini saya menjelaskan perbedaan berdasarkan pemahaman saya;
Seperti yang dinyatakan sebelumnya, metode inisialisasi memungkinkan Anda untuk mengatur nilai-nilai untuk instance objek pada pembuatan objek.
Tetapi bagaimana jika Anda ingin menetapkan nilai nanti, setelah instance dibuat, atau mengubahnya setelah diinisialisasi? Ini akan menjadi skenario di mana Anda akan menggunakan metode penyetel. ITULAH PERBEDAANNYA. Anda tidak harus "mengatur" keadaan tertentu saat Anda menggunakan metode attr_writer pada awalnya.
Kode di bawah ini adalah contoh penggunaan metode setter untuk mendeklarasikan nilai item_name untuk instance kelas Item ini. Perhatikan bahwa kami terus menggunakan metode getter attr_reader sehingga kami bisa mendapatkan nilai dan mencetaknya di layar, untuk berjaga-jaga jika Anda ingin menguji kodenya sendiri.
Kode di bawah ini adalah pengulangan contoh inisialisasi di atas di mana kita menggunakan inisialisasi untuk mengatur nilai objek dari item_name saat membuat.
Saya pikir bagian dari apa yang membingungkan Rubyists / programmer baru (seperti saya) adalah:
"Mengapa saya tidak bisa memberi tahu instance itu memiliki atribut tertentu (misalnya, nama) dan memberi nilai atribut itu semua dalam satu gerakan?"
Sedikit lebih digeneralisasi, tapi ini caranya saya mengklik:
Diberikan:
classPersonend
Kami belum mendefinisikan Orang sebagai sesuatu yang dapat memiliki nama atau atribut lainnya dalam hal ini.
Jadi, jika kita:
baby =Person.new
... dan coba beri mereka nama ...
baby.name ="Ruth"
Kami mendapatkan kesalahan karena, di Rubyland, objek kelas Person bukanlah sesuatu yang dikaitkan dengan atau mampu memiliki "nama" ... belum!
TETAPI kita dapat menggunakan salah satu metode yang diberikan (lihat jawaban sebelumnya) sebagai cara untuk mengatakan, "Sebuah instance dari kelas Person ( baby) sekarang dapat memiliki atribut yang disebut 'nama', oleh karena itu kami tidak hanya memiliki cara sintaksis untuk mendapatkan dan menetapkan nama itu, tetapi masuk akal bagi kita untuk melakukannya. "
Sekali lagi, mengenai pertanyaan ini dari sudut yang sedikit berbeda dan lebih umum, tetapi saya harap ini membantu contoh berikutnya dari class Person yang menemukan jalan mereka ke utas ini.
ownerdan balancebukan, secara teknis, metode , tetapi atribut. Kelas BankAccount tidak memiliki def ownerdan def balance. Jika ya, maka Anda dapat menggunakan dua perintah di bawah ini. Tetapi kedua metode itu tidak ada. Namun, Anda dapat mengakses atribut seolah-olah Anda akan mengakses metode via attr_accessor!! Karena itu kataattr_accessor . Atribut. Accessor. Ini mengakses atribut seperti Anda akan mengakses metode.
Menambahkan attr_accessor :balance, :ownermemungkinkan Anda untuk membaca dan menulis balancedan owner"metode". Sekarang Anda dapat menggunakan 2 metode terakhir.
Menentukan atribut yang dinamai untuk modul ini, di mana namanya adalah symbol.id2name, membuat variabel instan (@name) dan metode akses yang sesuai untuk membacanya. Juga membuat metode bernama name = untuk mengatur atribut.
Saya baru di ruby dan harus berurusan dengan memahami keanehan berikut. Mungkin bisa membantu orang lain di masa depan. Pada akhirnya seperti yang disebutkan di atas, di mana 2 fungsi (def myvar, def myvar =) keduanya secara implisit untuk mengakses @myvar, tetapi metode ini dapat diganti dengan deklarasi lokal.
classFoo
attr_accessor 'myvar'def initialize
@myvar="A"
myvar ="B"
puts @myvar# A
puts myvar # B - myvar declared above overrides myvar methodenddef test
puts @myvar# A
puts myvar # A - coming from myvar accessor
myvar ="C"# local myvar overrides accessor
puts @myvar# A
puts myvar # C
send "myvar=","E"# not running "myvar =", but instead calls setter for @myvar
puts @myvar# E
puts myvar # Cendend
Atribut adalah komponen kelas yang dapat diakses dari luar objek. Mereka dikenal sebagai properti di banyak bahasa pemrograman lainnya. Nilai-nilai mereka dapat diakses dengan menggunakan "notasi titik", seperti pada object_name.attribute_name. Tidak seperti Python dan beberapa bahasa lainnya, Ruby tidak mengizinkan variabel instan diakses langsung dari luar objek.
classCardef initialize
@wheels=4# This is an instance variableendend
c =Car.new
c.wheels # Output: NoMethodError: undefined method `wheels' for #<Car:0x00000000d43500>
Dalam contoh di atas, c adalah instance (objek) dari kelas Mobil. Kami mencoba untuk gagal membaca nilai variabel instance roda dari luar objek. Apa yang terjadi adalah bahwa Ruby mencoba memanggil metode bernama wheels di dalam objek c, tetapi tidak ada metode yang didefinisikan. Singkatnya, object_name.attribute_name mencoba memanggil metode bernama attribute_name di dalam objek. Untuk mengakses nilai variabel roda dari luar, kita perlu mengimplementasikan metode instance dengan nama itu, yang akan mengembalikan nilai variabel itu ketika dipanggil. Itu disebut metode accessor. Dalam konteks pemrograman umum, cara biasa untuk mengakses variabel instan dari luar objek adalah dengan menerapkan metode accessor, juga dikenal sebagai metode pengambil dan penyetel.
Dalam contoh berikut, kami telah menambahkan metode pengambil dan penyetel ke kelas Mobil untuk mengakses variabel roda dari luar objek. Ini bukan "cara Ruby" dalam mendefinisikan getter dan setter; ini hanya berfungsi untuk menggambarkan apa yang dilakukan oleh metode pengambil dan penyetel.
classCardef wheels # getter method@wheelsenddef wheels=(val)# setter method@wheels= val
endend
f =Car.new
f.wheels =4# The setter method was invoked
f.wheels # The getter method was invoked# Output: => 4
Contoh di atas berfungsi dan kode serupa biasanya digunakan untuk membuat metode pengambil dan penyetel dalam bahasa lain. Namun, Ruby menyediakan cara yang lebih sederhana untuk melakukan ini: tiga metode bawaan yang disebut attr_reader, attr_writer dan attr_acessor. Metode attr_reader membuat variabel instan dapat dibaca dari luar, attr_writer membuatnya dapat ditulis, dan attr_acessor membuatnya dapat dibaca dan ditulis.
Contoh di atas dapat ditulis ulang seperti ini.
classCar
attr_accessor :wheels
end
f =Car.new
f.wheels =4
f.wheels # Output: => 4
Pada contoh di atas, atribut wheels akan dapat dibaca dan ditulis dari luar objek. Jika alih-alih attr_accessor, kami menggunakan attr_reader, itu akan menjadi hanya-baca. Jika kami menggunakan attr_writer, itu akan menjadi hanya menulis. Ketiga metode itu bukan pengambil dan penyetel dalam diri mereka tetapi, ketika dipanggil, mereka menciptakan metode pengambil dan penyetel bagi kita. Mereka adalah metode yang secara dinamis (terprogram) menghasilkan metode lain; itu disebut metaprogramming.
Contoh pertama (lebih panjang), yang tidak menggunakan metode bawaan Ruby, hanya boleh digunakan ketika kode tambahan diperlukan dalam metode pengambil dan penyetel. Misalnya, metode penyetel mungkin perlu memvalidasi data atau melakukan perhitungan sebelum menetapkan nilai ke variabel instan.
Dimungkinkan untuk mengakses (baca dan tulis) variabel instan dari luar objek, dengan menggunakan instance_variable_get dan instance_variable_set metode bawaan. Namun, ini jarang dibenarkan dan biasanya ide yang buruk, karena mem-enkapsulasi cenderung mendatangkan segala macam malapetaka.
Fungsionalitas utama attr_accessor di atas yang lainnya adalah kemampuan mengakses data dari file lain.
Jadi Anda biasanya memiliki attr_reader atau attr_writer tetapi kabar baiknya adalah Ruby memungkinkan Anda menggabungkan keduanya bersama dengan attr_accessor. Saya menganggapnya sebagai metode saya untuk pergi karena metode ini lebih baik atau serbaguna. Juga, perhatikan bahwa dalam Rails, ini dihilangkan karena melakukannya untuk Anda di bagian belakang. Jadi dengan kata lain: Anda lebih baik menggunakan attr_acessor daripada dua lainnya karena Anda tidak perlu khawatir untuk menjadi spesifik, accessor mencakup semuanya. Saya tahu ini lebih merupakan penjelasan umum tetapi membantu saya sebagai pemula.
git
tidak ada hubungannya denganattr_accessor
. Git adalah software kontrol versi, sedangkanattr_accessor
adalah metode di Ruby .Jawaban:
Katakanlah Anda memiliki kelas
Person
.Jelas kami tidak pernah mendefinisikan metode
name
. Ayo lakukan itu.Aha, kita dapat membaca namanya, tetapi itu tidak berarti kita dapat menetapkan namanya. Itu adalah dua metode yang berbeda. Yang pertama disebut pembaca dan yang terakhir disebut penulis . Kami belum membuat penulis, jadi mari kita lakukan.
Luar biasa. Sekarang kita dapat menulis dan membaca variabel instan
@name
menggunakan metode pembaca dan penulis. Kecuali, ini sering dilakukan, mengapa buang waktu menulis metode ini setiap waktu? Kita bisa melakukannya dengan lebih mudah.Bahkan ini bisa berulang. Bila Anda ingin pembaca dan penulis gunakan saja accessor!
Bekerja dengan cara yang sama! Dan coba tebak: variabel instan
@name
di objek orang kita akan diatur seperti ketika kita melakukannya secara manual, sehingga Anda dapat menggunakannya dalam metode lain.Itu dia. Untuk memahami bagaimana
attr_reader
,,attr_writer
danattr_accessor
metode sebenarnya menghasilkan metode untuk Anda, baca jawaban lain, buku, dokumen ruby.sumber
attr_accessor
ini adalah metode yang dipanggil pada kelas saat ini, dan:name
merupakan parameter yang Anda berikan ke metode itu. Ini bukan sintaks khusus, ini metode panggilan yang sederhana. Jika Anda memberikannya@name
variabel, itu tidak masuk akal, karena @name akan berisinil
. Jadi itu seperti menulisattr_accessor nil
. Anda tidak meneruskannya variabel yang perlu dibuat, Anda meneruskan nama yang Anda inginkan variabel dipanggil.name
dan variabel@name
bukan hal yang sama. Jangan membingungkan mereka. Anda memiliki variabel instan@name
di kelas Anda, dan Anda menentukanattr_reader :name
untuk dapat membacanya dari luar. Tanpaattr_reader
tidak ada cara sederhana yang dapat Anda akses di@name
luar kelas Anda.attr_accessor adalah hanya sebuah metode . (Tautan harus memberikan wawasan lebih banyak tentang cara kerjanya - lihat pasangan metode yang dihasilkan, dan tutorial akan menunjukkan kepada Anda bagaimana menggunakannya.)
Kuncinya adalah bahwa
class
itu bukan definisi di Ruby (itu adalah "hanya definisi" dalam bahasa seperti C ++ dan Java), tetapi itu adalah ekspresi yang mengevaluasi . Selama evaluasi ini ketikaattr_accessor
metode dipanggil yang pada gilirannya memodifikasi kelas saat ini - ingat penerima implisit:, diself.attr_accessor
manaself
objek kelas "terbuka" pada titik ini.Kebutuhan
attr_accessor
dan teman, adalah, yah:Ruby, seperti Smalltalk, tidak mengizinkan variabel instan diakses di luar metode 1 untuk objek itu. Yaitu, variabel instance tidak dapat diakses dalam
x.y
bentuk seperti yang umum di katakan, Java atau bahkan Python. Dalam Rubyy
selalu diambil sebagai pesan untuk mengirim (atau "metode untuk memanggil"). Dengan demikianattr_*
metode membuat pembungkus yang proksi@variable
akses instance melalui metode yang dibuat secara dinamis.Boilerplate menyebalkan
Semoga ini menjelaskan beberapa detail kecil. Selamat coding.
1 Ini tidak sepenuhnya benar dan ada beberapa "teknik" di sekitar ini , tetapi tidak ada dukungan sintaks untuk akses "variabel instance publik".
sumber
attr_accessor
adalah (seperti yang dinyatakan @pst) hanya sebuah metode. Apa yang dilakukannya adalah menciptakan lebih banyak metode untuk Anda.Jadi kode ini di sini:
setara dengan kode ini:
Anda dapat menulis metode semacam ini sendiri di Ruby:
sumber
attr_accessor
dan akhirnya ditemukan di sini! Meskipun ini menyelesaikan masalah saya, tetapi saya ingin tahu di mana (buku / dokumen resmi) dapatkah saya menemukan contoh implementasi seperti ini?attr_accessor
sangat sederhana:adalah jalan pintas untuk:
itu tidak lebih dari pengambil / penyetel untuk suatu objek
sumber
Pada dasarnya mereka memalsukan atribut data yang dapat diakses publik, yang tidak dimiliki Ruby.
sumber
Ini hanya metode yang mendefinisikan metode pengambil dan penyetel untuk variabel instan. Contoh implementasi adalah:
sumber
Penjelasan Sederhana Tanpa Kode Apa Pun
Sebagian besar jawaban di atas menggunakan kode. Penjelasan ini mencoba menjawabnya tanpa menggunakan apa pun, melalui analogi / cerita:
Pihak luar tidak dapat mengakses rahasia internal CIA
Mari kita bayangkan tempat yang sangat rahasia: CIA. Tidak ada yang tahu apa yang terjadi di CIA selain dari orang-orang di dalam CIA. Dengan kata lain, orang eksternal tidak dapat mengakses informasi apa pun di CIA. Tetapi karena tidak ada gunanya memiliki organisasi yang sepenuhnya rahasia, informasi tertentu tersedia untuk dunia luar - hanya hal-hal yang CIA ingin semua orang tahu tentang tentu saja: misalnya Direktur CIA, bagaimana ramah lingkungan departemen ini dibandingkan kepada semua departemen pemerintah lainnya, dll. Informasi lain: mis. siapa yang merupakan agen rahasia di Irak atau Afghanistan - hal-hal semacam ini mungkin akan tetap menjadi rahasia selama 150 tahun ke depan.
Jika Anda berada di luar CIA, Anda hanya dapat mengakses informasi yang telah disediakan untuk publik. Atau untuk menggunakan bahasa CIA Anda hanya dapat mengakses informasi yang "dihapus".
Informasi yang ingin disediakan CIA untuk masyarakat umum di luar CIA disebut: atribut.
Arti dari atribut baca dan tulis:
Dalam kasus CIA, sebagian besar atribut adalah "hanya baca". Ini berarti jika Anda adalah pihak di luar CIA, Anda dapat bertanya: "siapa direktur CIA?" dan Anda akan mendapatkan jawaban langsung. Tetapi yang tidak bisa Anda lakukan dengan atribut "read only" adalah membuat perubahan pada CIA. mis. Anda tidak dapat membuat panggilan telepon dan tiba-tiba memutuskan bahwa Anda ingin Kim Kardashian menjadi Direktur, atau Anda ingin Paris Hilton menjadi Panglima Tertinggi.
Jika atribut memberi Anda akses "tulis", maka Anda dapat membuat perubahan jika Anda ingin, bahkan jika Anda berada di luar. Jika tidak, satu-satunya hal yang dapat Anda lakukan adalah membaca.
Dengan kata lain, pengakses memungkinkan Anda untuk membuat pertanyaan, atau membuat perubahan, ke organisasi yang sebaliknya tidak membiarkan orang luar masuk, tergantung pada apakah pengakses membaca atau menulis pengakses.
Objek di dalam kelas dapat dengan mudah mengakses satu sama lain
Persis sama dengan kelas dan kemampuan Anda untuk mengakses variabel, properti, dan metode di dalamnya. HTH! Ada pertanyaan, silakan tanyakan dan saya harap saya bisa mengklarifikasi.
sumber
Jika Anda terbiasa dengan konsep OOP, Anda harus terbiasa dengan metode pengambil dan penyetel. attr_accessor melakukan hal yang sama di Ruby.
Getter dan Setter secara Umum
Metode Setter
Metode pengambil
Metode Getter dan Setter di Ruby
sumber
Saya juga menghadapi masalah ini dan menulis jawaban yang agak panjang untuk pertanyaan ini. Sudah ada beberapa jawaban bagus untuk ini, tetapi siapa pun yang mencari klarifikasi lebih lanjut, saya harap jawaban saya dapat membantu
Inisialisasi Metode
Initialize memungkinkan Anda untuk mengatur data ke instance objek saat membuat instance daripada harus mengaturnya pada baris terpisah dalam kode Anda setiap kali Anda membuat instance baru dari kelas.
Dalam kode di atas kita menetapkan nama "Denis" menggunakan metode inisialisasi dengan melewati Dennis melalui parameter di Inisialisasi. Jika kami ingin menetapkan nama tanpa metode inisialisasi kami dapat melakukannya seperti ini:
Dalam kode di atas, kita menetapkan nama dengan memanggil metode setter attr_accessor menggunakan person.name, daripada mengatur nilai saat inisialisasi objek.
Kedua "metode" dalam melakukan pekerjaan ini, tetapi menginisialisasi menghemat waktu dan baris kode.
Ini adalah satu-satunya tugas menginisialisasi. Anda tidak dapat memanggil inisialisasi sebagai metode. Untuk benar-benar mendapatkan nilai-nilai objek instan Anda perlu menggunakan getter dan setter (attr_reader (get), attr_writer (set), dan attr_accessor (keduanya)). Lihat di bawah untuk detail lebih lanjut tentang itu.
Getters, Setter (attr_reader, attr_writer, attr_accessor)
Getters, attr_reader: Seluruh tujuan pengambil adalah untuk mengembalikan nilai variabel instance tertentu. Kunjungi kode contoh di bawah ini untuk rinciannya.
Dalam kode di atas Anda memanggil metode "item_name" dan "kuantitas" pada contoh Item "example". "Menempatkan example.item_name" dan "example.quantity" akan mengembalikan (atau "get") nilai untuk parameter yang diteruskan ke dalam "example" dan menampilkannya ke layar.
Untungnya di Ruby ada metode inheren yang memungkinkan kita untuk menulis kode ini secara lebih ringkas; metode attr_reader. Lihat kode di bawah ini;
Sintaks ini bekerja dengan cara yang persis sama, hanya saja itu menyelamatkan kita enam baris kode. Bayangkan jika Anda memiliki 5 status yang lebih disebabkan oleh kelas Item? Kode akan lama cepat.
Setter, attr_writer: Apa yang membuat saya bingung pada awalnya dengan metode setter adalah bahwa di mata saya tampaknya melakukan fungsi yang identik dengan metode inisialisasi. Di bawah ini saya menjelaskan perbedaan berdasarkan pemahaman saya;
Seperti yang dinyatakan sebelumnya, metode inisialisasi memungkinkan Anda untuk mengatur nilai-nilai untuk instance objek pada pembuatan objek.
Tetapi bagaimana jika Anda ingin menetapkan nilai nanti, setelah instance dibuat, atau mengubahnya setelah diinisialisasi? Ini akan menjadi skenario di mana Anda akan menggunakan metode penyetel. ITULAH PERBEDAANNYA. Anda tidak harus "mengatur" keadaan tertentu saat Anda menggunakan metode attr_writer pada awalnya.
Kode di bawah ini adalah contoh penggunaan metode setter untuk mendeklarasikan nilai item_name untuk instance kelas Item ini. Perhatikan bahwa kami terus menggunakan metode getter attr_reader sehingga kami bisa mendapatkan nilai dan mencetaknya di layar, untuk berjaga-jaga jika Anda ingin menguji kodenya sendiri.
Kode di bawah ini adalah contoh penggunaan attr_writer untuk sekali lagi mempersingkat kode kami dan menghemat waktu kami.
Kode di bawah ini adalah pengulangan contoh inisialisasi di atas di mana kita menggunakan inisialisasi untuk mengatur nilai objek dari item_name saat membuat.
attr_accessor: Melakukan fungsi attr_reader dan attr_writer, menghemat satu baris kode lagi.
sumber
Saya pikir bagian dari apa yang membingungkan Rubyists / programmer baru (seperti saya) adalah:
"Mengapa saya tidak bisa memberi tahu instance itu memiliki atribut tertentu (misalnya, nama) dan memberi nilai atribut itu semua dalam satu gerakan?"
Sedikit lebih digeneralisasi, tapi ini caranya saya mengklik:
Diberikan:
Kami belum mendefinisikan Orang sebagai sesuatu yang dapat memiliki nama atau atribut lainnya dalam hal ini.
Jadi, jika kita:
... dan coba beri mereka nama ...
Kami mendapatkan kesalahan karena, di Rubyland, objek kelas Person bukanlah sesuatu yang dikaitkan dengan atau mampu memiliki "nama" ... belum!
TETAPI kita dapat menggunakan salah satu metode yang diberikan (lihat jawaban sebelumnya) sebagai cara untuk mengatakan, "Sebuah instance dari kelas Person (
baby
) sekarang dapat memiliki atribut yang disebut 'nama', oleh karena itu kami tidak hanya memiliki cara sintaksis untuk mendapatkan dan menetapkan nama itu, tetapi masuk akal bagi kita untuk melakukannya. "Sekali lagi, mengenai pertanyaan ini dari sudut yang sedikit berbeda dan lebih umum, tetapi saya harap ini membantu contoh berikutnya dari class Person yang menemukan jalan mereka ke utas ini.
sumber
Sederhananya akan menentukan setter dan pengambil untuk kelas.
Catat itu
Begitu
setara dengan mendefinisikan setter dan pengambil untuk kelas.
sumber
Cukup
attr-accessor
membuatgetter
dansetter
metode untuk atribut yang ditentukansumber
Cara lain untuk memahaminya adalah dengan mencari tahu kode kesalahan apa yang dihilangkan dengan memilikinya
attr_accessor
.Contoh:
Metode berikut tersedia:
Metode berikut melempar kesalahan:
owner
danbalance
bukan, secara teknis, metode , tetapi atribut. Kelas BankAccount tidak memilikidef owner
dandef balance
. Jika ya, maka Anda dapat menggunakan dua perintah di bawah ini. Tetapi kedua metode itu tidak ada. Namun, Anda dapat mengakses atribut seolah-olah Anda akan mengakses metode viaattr_accessor
!! Karena itu kataattr_accessor
. Atribut. Accessor. Ini mengakses atribut seperti Anda akan mengakses metode.Menambahkan
attr_accessor :balance, :owner
memungkinkan Anda untuk membaca dan menulisbalance
danowner
"metode". Sekarang Anda dapat menggunakan 2 metode terakhir.sumber
Menentukan atribut yang dinamai untuk modul ini, di mana namanya adalah symbol.id2name, membuat variabel instan (@name) dan metode akses yang sesuai untuk membacanya. Juga membuat metode bernama name = untuk mengatur atribut.
sumber
Untuk meringkas atribut accessor alias attr_accessor memberi Anda dua metode gratis.
Seperti di Jawa mereka dipanggil getter dan setter.
Banyak jawaban telah menunjukkan contoh yang baik jadi saya hanya akan singkat.
#the_attribute
dan
# the_attribute =
Di dokumen ruby lama, tag hash # berarti metode. Itu juga bisa menyertakan awalan nama kelas ... MyClass # my_method
sumber
Saya baru di ruby dan harus berurusan dengan memahami keanehan berikut. Mungkin bisa membantu orang lain di masa depan. Pada akhirnya seperti yang disebutkan di atas, di mana 2 fungsi (def myvar, def myvar =) keduanya secara implisit untuk mengakses @myvar, tetapi metode ini dapat diganti dengan deklarasi lokal.
sumber
Atribut dan metode accessor
Atribut adalah komponen kelas yang dapat diakses dari luar objek. Mereka dikenal sebagai properti di banyak bahasa pemrograman lainnya. Nilai-nilai mereka dapat diakses dengan menggunakan "notasi titik", seperti pada object_name.attribute_name. Tidak seperti Python dan beberapa bahasa lainnya, Ruby tidak mengizinkan variabel instan diakses langsung dari luar objek.
Dalam contoh di atas, c adalah instance (objek) dari kelas Mobil. Kami mencoba untuk gagal membaca nilai variabel instance roda dari luar objek. Apa yang terjadi adalah bahwa Ruby mencoba memanggil metode bernama wheels di dalam objek c, tetapi tidak ada metode yang didefinisikan. Singkatnya, object_name.attribute_name mencoba memanggil metode bernama attribute_name di dalam objek. Untuk mengakses nilai variabel roda dari luar, kita perlu mengimplementasikan metode instance dengan nama itu, yang akan mengembalikan nilai variabel itu ketika dipanggil. Itu disebut metode accessor. Dalam konteks pemrograman umum, cara biasa untuk mengakses variabel instan dari luar objek adalah dengan menerapkan metode accessor, juga dikenal sebagai metode pengambil dan penyetel.
Dalam contoh berikut, kami telah menambahkan metode pengambil dan penyetel ke kelas Mobil untuk mengakses variabel roda dari luar objek. Ini bukan "cara Ruby" dalam mendefinisikan getter dan setter; ini hanya berfungsi untuk menggambarkan apa yang dilakukan oleh metode pengambil dan penyetel.
Contoh di atas berfungsi dan kode serupa biasanya digunakan untuk membuat metode pengambil dan penyetel dalam bahasa lain. Namun, Ruby menyediakan cara yang lebih sederhana untuk melakukan ini: tiga metode bawaan yang disebut attr_reader, attr_writer dan attr_acessor. Metode attr_reader membuat variabel instan dapat dibaca dari luar, attr_writer membuatnya dapat ditulis, dan attr_acessor membuatnya dapat dibaca dan ditulis.
Contoh di atas dapat ditulis ulang seperti ini.
Pada contoh di atas, atribut wheels akan dapat dibaca dan ditulis dari luar objek. Jika alih-alih attr_accessor, kami menggunakan attr_reader, itu akan menjadi hanya-baca. Jika kami menggunakan attr_writer, itu akan menjadi hanya menulis. Ketiga metode itu bukan pengambil dan penyetel dalam diri mereka tetapi, ketika dipanggil, mereka menciptakan metode pengambil dan penyetel bagi kita. Mereka adalah metode yang secara dinamis (terprogram) menghasilkan metode lain; itu disebut metaprogramming.
Contoh pertama (lebih panjang), yang tidak menggunakan metode bawaan Ruby, hanya boleh digunakan ketika kode tambahan diperlukan dalam metode pengambil dan penyetel. Misalnya, metode penyetel mungkin perlu memvalidasi data atau melakukan perhitungan sebelum menetapkan nilai ke variabel instan.
Dimungkinkan untuk mengakses (baca dan tulis) variabel instan dari luar objek, dengan menggunakan instance_variable_get dan instance_variable_set metode bawaan. Namun, ini jarang dibenarkan dan biasanya ide yang buruk, karena mem-enkapsulasi cenderung mendatangkan segala macam malapetaka.
sumber
Hmmm. Banyak jawaban bagus. Ini beberapa sen saya di atasnya.
attr_accessor
adalah metode sederhana yang membantu kita dalam membersihkan ( DRY-ing ) sampai mengulangigetter and setter
metode.Sehingga kita bisa lebih fokus menulis logika bisnis dan tidak khawatir tentang setter dan getter.
sumber
Fungsionalitas utama attr_accessor di atas yang lainnya adalah kemampuan mengakses data dari file lain.
Jadi Anda biasanya memiliki attr_reader atau attr_writer tetapi kabar baiknya adalah Ruby memungkinkan Anda menggabungkan keduanya bersama dengan attr_accessor. Saya menganggapnya sebagai metode saya untuk pergi karena metode ini lebih baik atau serbaguna. Juga, perhatikan bahwa dalam Rails, ini dihilangkan karena melakukannya untuk Anda di bagian belakang. Jadi dengan kata lain: Anda lebih baik menggunakan attr_acessor daripada dua lainnya karena Anda tidak perlu khawatir untuk menjadi spesifik, accessor mencakup semuanya. Saya tahu ini lebih merupakan penjelasan umum tetapi membantu saya sebagai pemula.
Semoga ini bisa membantu!
sumber