Saya mengalami kesulitan memahami attr_accessor
di Ruby .
Adakah yang bisa menjelaskan hal ini kepada saya?
git
tidak ada hubungannya dengan attr_accessor
. Git adalah software kontrol versi, sedangkan attr_accessor
adalah metode di Ruby .
Saya mengalami kesulitan memahami attr_accessor
di Ruby .
Adakah yang bisa menjelaskan hal ini kepada saya?
git
tidak ada hubungannya dengan attr_accessor
. Git adalah software kontrol versi, sedangkan attr_accessor
adalah metode di Ruby .
Jawaban:
Katakanlah Anda memiliki kelas Person
.
class Person
end
person = Person.new
person.name # => no method error
Jelas kami tidak pernah mendefinisikan metode name
. Ayo lakukan itu.
class Person
def name
@name # simply returning an instance variable @name
end
end
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.
class Person
def name
@name
end
def name=(str)
@name = str
end
end
person = Person.new
person.name = 'Dennis'
person.name # => "Dennis"
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.
class Person
attr_reader :name
attr_writer :name
end
Bahkan ini bisa berulang. Bila Anda ingin pembaca dan penulis gunakan saja accessor!
class Person
attr_accessor :name
end
person = Person.new
person.name = "Dennis"
person.name # => "Dennis"
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.
class Person
attr_accessor :name
def greeting
"Hello #{@name}"
end
end
person = Person.new
person.name = "Dennis"
person.greeting # => "Hello Dennis"
Itu dia. Untuk memahami bagaimana attr_reader
,, attr_writer
dan attr_accessor
metode sebenarnya menghasilkan metode untuk Anda, baca jawaban lain, buku, dokumen ruby.
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 berisi nil
. Jadi itu seperti menulis attr_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 menentukan attr_reader :name
untuk dapat membacanya dari luar. Tanpa attr_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 ketika attr_accessor
metode dipanggil yang pada gilirannya memodifikasi kelas saat ini - ingat penerima implisit:, di self.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 Ruby y
selalu diambil sebagai pesan untuk mengirim (atau "metode untuk memanggil"). Dengan demikian attr_*
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".
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:
class Foo
attr_accessor :bar
end
setara dengan kode ini:
class Foo
def bar
@bar
end
def bar=( new_value )
@bar = new_value
end
end
Anda dapat menulis metode semacam ini sendiri di Ruby:
class Module
def 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
end
end
end
class Foo
var :bar
end
f = Foo.new
p f.bar #=> nil
f.bar = 42
p f.bar #=> 42
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:
attr_accessor :foo
adalah jalan pintas untuk:
def foo=(val)
@foo = val
end
def foo
@foo
end
itu tidak lebih dari pengambil / penyetel untuk suatu objek
Pada dasarnya mereka memalsukan atribut data yang dapat diakses publik, yang tidak dimiliki Ruby.
Ini hanya metode yang mendefinisikan metode pengambil dan penyetel untuk variabel instan. Contoh implementasi adalah:
def self.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 setter
end
end
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.
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
class Person
def name
@name
end
def name=(str)
@name = str
end
end
person = Person.new
person.name = 'Eshaan'
person.name # => "Eshaan"
Metode Setter
def name=(val)
@name = val
end
Metode pengambil
def name
@name
end
Metode Getter dan Setter di Ruby
class Person
attr_accessor :name
end
person = Person.new
person.name = "Eshaan"
person.name # => "Eshaan"
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.
class Person
def initialize(name)
@name = name
end
def greeting
"Hello #{@name}"
end
end
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:
class Person
attr_accessor :name
# def initialize(name)
# @name = name
# end
def greeting
"Hello #{name}"
end
end
person = Person.new
person.name = "Dennis"
puts person.greeting
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.
class Item
def initialize(item_name, quantity)
@item_name = item_name
@quantity = quantity
end
def item_name
@item_name
end
def quantity
@quantity
end
end
example = Item.new("TV",2)
puts example.item_name
puts example.quantity
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;
class Item
attr_reader :item_name, :quantity
def initialize(item_name, quantity)
@item_name = item_name
@quantity = quantity
end
end
item = Item.new("TV",2)
puts item.item_name
puts item.quantity
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.
class Item
attr_reader :item_name
def item_name=(str)
@item_name = (str)
end
end
Kode di bawah ini adalah contoh penggunaan attr_writer untuk sekali lagi mempersingkat kode kami dan menghemat waktu kami.
class Item
attr_reader :item_name
attr_writer :item_name
end
item = Item.new
puts item.item_name = "TV"
Kode di bawah ini adalah pengulangan contoh inisialisasi di atas di mana kita menggunakan inisialisasi untuk mengatur nilai objek dari item_name saat membuat.
class Item
attr_reader :item_name
def initialize(item_name)
@item_name = item_name
end
end
item = Item.new("TV")
puts item.item_name
attr_accessor: Melakukan fungsi attr_reader dan attr_writer, menghemat satu baris kode lagi.
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:
class Person
end
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.
Sederhananya akan menentukan setter dan pengambil untuk kelas.
Catat itu
attr_reader :v is equivalant to
def v
@v
end
attr_writer :v is equivalant to
def v=(value)
@v=value
end
Begitu
attr_accessor :v which means
attr_reader :v; attr_writer :v
setara dengan mendefinisikan setter dan pengambil untuk kelas.
Cara lain untuk memahaminya adalah dengan mencari tahu kode kesalahan apa yang dihilangkan dengan memilikinya attr_accessor
.
Contoh:
class BankAccount
def initialize( account_owner )
@owner = account_owner
@balance = 0
end
def deposit( amount )
@balance = @balance + amount
end
def withdraw( amount )
@balance = @balance - amount
end
end
Metode berikut tersedia:
$ bankie = BankAccout.new("Iggy")
$ bankie
$ bankie.deposit(100)
$ bankie.withdraw(5)
Metode berikut melempar kesalahan:
$ bankie.owner #undefined method `owner'...
$ bankie.balance #undefined method `balance'...
owner
dan balance
bukan, secara teknis, metode , tetapi atribut. Kelas BankAccount tidak memiliki def owner
dan 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, :owner
memungkinkan Anda untuk membaca dan menulis balance
dan owner
"metode". Sekarang Anda dapat menggunakan 2 metode terakhir.
$ bankie.balance
$ bankie.owner
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.
module Mod
attr_accessor(:one, :two)
end
Mod.instance_methods.sort #=> [:one, :one=, :two, :two=]
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
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.
class Foo
attr_accessor 'myvar'
def initialize
@myvar = "A"
myvar = "B"
puts @myvar # A
puts myvar # B - myvar declared above overrides myvar method
end
def 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 # C
end
end
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.
class Car
def initialize
@wheels = 4 # This is an instance variable
end
end
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.
class Car
def wheels # getter method
@wheels
end
def wheels=(val) # setter method
@wheels = val
end
end
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.
class Car
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.
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.
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!