Saya mengalami waktu yang sulit memahami attr_accessor
di Ruby. Seseorang dapat menjelaskan hal ini kepada saya?
Let's mengatakan anda memiliki kelas Orang
.
class Person
end
person = Person.new
person.name # => no method error
Jelas kita tidak pernah didefinisikan metode nama
. Let's melakukan 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 nama itu, tapi itu doesn't berarti kita dapat menetapkan nama. Mereka adalah dua metode yang berbeda. Mantan disebut reader dan terakhir ini disebut penulis. Kami didn't membuat penulis belum begitu let's melakukan itu.
class Person
def name
@name
end
def name=(str)
@name = str
end
end
person = Person.new
person.name = 'Dennis'
person.name # => "Dennis"
Yang mengagumkan. Sekarang kita bisa menulis dan membaca variabel instance @nama
menggunakan pembaca dan penulis metode. Kecuali, hal ini dilakukan agar sering, mengapa membuang-buang waktu menulis metode ini setiap waktu? Kita dapat melakukannya dengan lebih mudah.
class Person
attr_reader :name
attr_writer :name
end
Bahkan hal ini bisa berulang-ulang. Bila anda ingin para pembaca dan penulis hanya menggunakan accessor!
class Person
attr_accessor :name
end
person = Person.new
person.name = "Dennis"
person.name # => "Dennis"
Bekerja dengan cara yang sama! Dan coba tebak: contoh variabel @nama
kami orang objek yang akan diatur sama 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"
Yang's ini. Dalam rangka untuk memahami bagaimana attr_reader
, attr_writer
, dan attr_accessor
metode yang benar-benar menghasilkan metode untuk anda, baca jawaban yang lain, buku-buku, ruby docs.
attr_accessor adalah hanya sebuah metode. (Link harus memberikan wawasan yang lebih dengan cara kerjanya - melihat pasangan dari metode yang dihasilkan, dan tutorial harus menunjukkan anda bagaimana untuk menggunakannya.)
Kuncinya adalah bahwa kelas
tidak definisi di Ruby (hal ini "definisi" dalam bahasa seperti C++ dan Java), tapi itu adalah ekspresi yang mengevaluasi. Selama ini evaluasi ketika attr_accessor
metode ini dipanggil yang pada gilirannya memodifikasi saat ini kelas - ingat implisit penerima: diri.attr_accessor
, di mana diri
adalah "terbuka" kelas objek pada titik ini.
Kebutuhan untuk attr_accessor
dan teman-teman,, yah:
Ruby, seperti Smalltalk, tidak memungkinkan instance variable dapat diakses di luar metode1 untuk objek tersebut. Artinya, contoh variabel tidak dapat diakses di x.y
bentuk seperti yang umum di katakan, Jawa atau bahkan Python. Di Ruby y
selalu diambil sebagai pesan untuk mengirim (atau "metode untuk call"). Dengan demikian attr_*
metode membuat pembungkus yang rapat umum contoh @variabel
akses melalui dibuat secara dinamis metode.
Boilerplate menyebalkan
Harap ini menjelaskan beberapa detail kecil. Happy coding.
1 Ini isn't benar ketat dan ada beberapa "teknik" di sekitar this, tetapi tidak ada dukungan sintaks untuk "semua variabel instance" akses.
attr_accessor
adalah (seperti @pst menyatakan) hanya metode. Apa yang dilakukannya adalah menciptakan metode yang lebih untuk anda.
Jadi ini kode berikut:
class Foo
attr_accessor :bar
end
ini setara dengan kode ini:
class Foo
def bar
@bar
end
def bar=( new_value )
@bar = new_value
end
end
Anda dapat menulis semacam ini metode sendiri dalam 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
Itu hanya sebuah metode yang mendefinisikan getter dan setter metode untuk instance variable. Contoh implementasi akan sama:
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 atas menggunakan kode. Penjelasan ini mencoba untuk menjawab itu tanpa menggunakan apapun, melalui analogi/cerita:
Pihak luar tidak dapat mengakses internal CIA rahasia
Jika anda're luar CIA, anda hanya dapat mengakses informasi yang telah dibuat tersedia untuk umum. Atau menggunakan CIA bahasa anda hanya dapat mengakses informasi yang "dibersihkan".
Informasi bahwa CIA ingin membuat tersedia untuk umum di luar CIA disebut: atribut.
Makna dari membaca dan menulis atribut:
Dalam kasus CIA, yang paling atribut "baca hanya". Ini berarti jika anda adalah pihak eksternal untuk CIA, anda dapat tanya: "yang merupakan direktur CIA?" dan anda akan mendapatkan jawaban langsung. Tapi apa yang anda tidak hubungannya dengan "baca hanya" atribut adalah untuk membuat perubahan perubahan dalam CIA. misalnya, anda tidak dapat membuat panggilan telepon dan tiba-tiba memutuskan yang anda inginkan Kim Kardashian untuk menjadi Direktur, atau yang anda inginkan Paris Hilton untuk menjadi Panglima.
Jika atribut memberi anda "menulis" akses, maka anda bisa 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 accesor memungkinkan anda untuk membuat pertanyaan, atau untuk membuat perubahan, untuk organisasi yang dinyatakan tidak membiarkan orang luar dalam, tergantung pada apakah accesor membaca atau menulis accesor.
Benda-benda di dalam kelas dapat dengan mudah mengakses satu sama lain
Hal yang sama persis dengan kelas dan kemampuan anda untuk mengakses variabel, sifat dan metode dalam diri mereka. HTH! Setiap pertanyaan, silakan bertanya dan saya berharap saya bisa memperjelas.
Jika anda sudah familiar dengan konsep OOP, Anda harus akrab dengan getter dan setter method. attr_accessor melakukan hal yang sama di Ruby.
Getter dan Setter pada Umumnya Cara
class Person
def name
@name
end
def name=(str)
@name = str
end
end
person = Person.new
person.name = 'Eshaan'
person.name # => "Eshaan"
Metode Penyetel
def name=(val)
@name = val
end
Getter
def name
@name
end
Getter dan Setter method Ruby
class Person
attr_accessor :name
end
person = Person.new
person.name = "Eshaan"
person.name # => "Eshaan"
Saya menghadapi masalah ini juga dan menulis yang agak panjang jawaban untuk pertanyaan ini. Ada beberapa jawaban yang besar ini sudah, tapi orang yang mencari penjelasan lebih lanjut, saya harap jawaban saya dapat membantu
Menginisialisasi Metode
Menginisialisasi memungkinkan anda untuk mengatur data untuk contoh objek pada penciptaan contoh daripada harus mengatur mereka pada baris terpisah dalam kode anda setiap kali anda membuat sebuah instance baru dari class.
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 setting nama "Denis" menggunakan metode initialize dengan melewati Dennis melalui parameter dalam Menginisialisasi. Jika kita ingin mengatur nama tanpa menginisialisasi metode kita bisa 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 menyebut attr_accessor setter menggunakan metode orang.nama, daripada menetapkan nilai-nilai pada inisialisasi objek.
Kedua "metode" melakukan pekerjaan ini, tapi menginisialisasi menghemat waktu dan baris kode.
Ini adalah satu-satunya pekerjaan menginisialisasi. Anda tidak dapat memanggil menginisialisasi sebagai metode. Untuk benar-benar mendapatkan nilai-nilai dari sebuah instance objek yang anda butuhkan untuk menggunakan getter dan setter (attr_reader (mendapatkan), attr_writer(set), dan attr_accessor(baik)). Lihat di bawah untuk detail lebih lanjut tentang mereka.
Getter, Setter (attr_reader, attr_writer, attr_accessor)
Getter, attr_reader: seluruh tujuan dari inisiatif ini adalah untuk mengembalikan nilai tertentu variabel instance. Kunjungi sampel kode di bawah ini untuk rincian tentang hal ini.
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 "contoh". "Yang menempatkan contoh.item_name" dan "misalnya.kuantitas" akan kembali (atau "get") nilai parameter yang dilewatkan ke dalam "contoh" dan menampilkannya ke layar.
Untungnya di Ruby ada yang melekat metode yang memungkinkan kita untuk menulis kode ini lebih ringkas; yang attr_reader metode. 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 itu menyelamatkan kita enam baris kode. Bayangkan jika anda memiliki 5 negara yang lebih disebabkan oleh Item kelas? Kode akan mendapatkan panjang dengan cepat.
Setter, attr_writer: Apa yang terlintas di pertama dengan penyetel yang di mata saya tampak untuk melakukan yang identik fungsi untuk menginisialisasi metode. Di bawah ini saya menjelaskan perbedaan berdasarkan pemahaman saya;
Seperti yang dinyatakan sebelumnya, menginisialisasi metode ini memungkinkan anda untuk mengatur nilai-nilai untuk sebuah instance dari sebuah objek pada objek penciptaan.
Tapi bagaimana jika anda ingin mengatur nilai-nilai kemudian, setelah contoh diciptakan, atau mengubahnya setelah mereka telah diinisialisasi? Ini akan menjadi sebuah skenario di mana anda akan menggunakan metode penyetel. ITU ADALAH PERBEDAAN. Anda tidak harus "mengatur" negara tertentu ketika anda menggunakan attr_writer metode awalnya.
Kode berikut adalah contoh menggunakan metode penyetel untuk menyatakan nilai item_name ini misalnya Item kelas. Perhatikan bahwa kita terus menggunakan metode getter attr_reader sehingga kita bisa mendapatkan nilai-nilai dan mencetaknya ke layar, hanya dalam kasus anda ingin menguji kode anda sendiri.
class Item
attr_reader :item_name
def item_name=(str)
@item_name = (str)
end
end
Kode berikut adalah contoh menggunakan attr_writer untuk sekali lagi mempersingkat kode kita dan menyelamatkan kita waktu.
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 dari menginisialisasi contoh di atas di mana kita menggunakan menginisialisasi untuk mengatur objek nilai item_name pada penciptaan.
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 kedua attr_reader dan attr_writer, menghemat lebih satu baris kode.
Saya pikir bagian dari apa yang membingungkan baru Rubyists/programmer (seperti saya) adalah:
"Mengapa't aku hanya memberitahu misalnya memiliki atribut tertentu (misalnya, nama) dan memberikan atribut yang nilai semua dalam satu kejadian?"
Sedikit lebih umum, tapi ini adalah bagaimana saya sadari:
Mengingat:
class Person
end
Kami belum't didefinisikan Orang sebagai sesuatu yang dapat memiliki nama atau atribut lainnya untuk hal itu.
Jadi jika kita kemudian:
baby = Person.new
...dan mencoba untuk memberi mereka nama...
baby.name = "Ruth"
Kita mendapatkan error karena, di Rubyland, orang-Orang kelas objek adalah bukan sesuatu yang berhubungan dengan atau mampu memiliki "" ... belum!
TAPI kita dapat menggunakan suatu metode (lihat jawaban sebelumnya) sebagai cara untuk mengatakan, "sebuah instance dari sebuah kelas Orang (baby
) dapat sekarang memiliki atribut yang disebut 'nama', oleh karena itu kami tidak hanya memiliki sintaksis cara mendapatkan dan menetapkan nama itu, tapi itu masuk akal bagi kita untuk melakukannya."
Lagi, memukul pertanyaan ini dari yang sedikit berbeda dan lebih umum sudut, tapi saya harap ini membantu berikutnya instance dari class Orang yang menemukan jalan mereka ke thread ini.
Sederhananya itu akan menentukan setter dan getter untuk kelas.
Perhatikan bahwa
attr_reader :v is equivalant to
def v
@v
end
attr_writer :v is equivalant to
def v=(value)
@v=value
end
Jadi
attr_accessor :v which means
attr_reader :v; attr_writer :v
yang equivalant untuk menentukan setter dan getter untuk kelas.
Cara lain untuk memahami hal ini adalah untuk mengetahui apa itu kode kesalahan menghilangkan dengan memiliki 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
Berikut metode yang tersedia:
$ bankie = BankAccout.new("Iggy")
$ bankie
$ bankie.deposit(100)
$ bankie.withdraw(5)
Berikut metode melempar kesalahan:
$ bankie.owner #undefined method `owner'...
$ bankie.balance #undefined method `balance'...
pemilik
dan balance
tidak, secara teknis, metode, tapi atribut. Rekening bank kelas tidak memiliki def pemilik
dan def keseimbangan
. Jika tidak, maka anda dapat menggunakan dua perintah di bawah ini. Tapi dua metode aren't ada. Namun, anda dapat: akses atribut seperti jika anda'a akses metode melalui attr_accessor
!! Maka kata attr_accessor
. Atribut. Pengakses. Mengakses atribut seperti anda akan mengakses sebuah metode.
Menambahkan attr_accessor :keseimbangan, :pemilik
memungkinkan anda untuk membaca dan menulis keseimbangan
dan pemilik
"metode". Sekarang anda dapat menggunakan 2 metode.
$ bankie.balance
$ bankie.owner
Mendefinisikan sebuah nama atribut untuk modul ini, di mana nama adalah simbol.id2name, menciptakan sebuah instance variabel (@nama) dan sesuai metode akses untuk membacanya. Juga menciptakan metode yang disebut nama= 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.
Seperti di Jawa, mereka bisa disebut getter dan setter.
Banyak jawaban telah menunjukkan contoh yang baik jadi saya'm hanya akan menjadi singkat.
#the_attribute
dan
#the_attribute=
Di old ruby docs hash tag # berarti metode. Itu juga bisa termasuk nama kelas awalan... MyClass#my_method
Saya baru ruby dan hanya berurusan dengan pengertian berikut keanehan. Mungkin membantu orang lain di masa depan. Pada akhirnya itu adalah seperti yang telah disebutkan di atas, di mana 2 fungsi (def myvar, def myvar=) kedua mendapatkan implisit untuk mengakses @myvar, tetapi metode ini dapat diganti oleh lokal deklarasi.
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 kelas komponen yang dapat diakses dari luar objek. Mereka dikenal sebagai properti dalam banyak bahasa pemrograman lainnya. Nilai-nilai mereka dapat diakses dengan menggunakan "notasi titik", seperti di object_name.attribute_name. Tidak seperti Python dan beberapa bahasa lain, Ruby tidak memungkinkan misalnya variabel-variabel yang dapat diakses secara 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 (object) dari kelas Mobil. Kami mencoba gagal untuk membaca nilai dari roda variabel instance dari luar objek. Apa yang terjadi adalah bahwa Ruby mencoba untuk memanggil sebuah metode bernama roda dalam c objek, tetapi tidak ada metode tersebut didefinisikan. Singkatnya, object_name.attribute_name mencoba untuk memanggil sebuah metode bernama attribute_name dalam objek. Untuk mengakses nilai dari roda variabel dari luar, kita perlu menerapkan metode contoh dengan nama itu, yang akan mengembalikan nilai dari variabel itu ketika dipanggil. Yang's disebut accessor method. Dalam pemrograman umum konteks, dengan cara yang biasa untuk mengakses instance variable dari luar objek adalah dengan menerapkan metode accessor, juga dikenal sebagai getter dan setter method. Pengambil memungkinkan nilai dari sebuah variabel yang didefinisikan di dalam kelas dapat dibaca dari luar dan setter memungkinkan untuk menjadi tertulis dari luar.
Dalam contoh berikut, kita telah menambahkan getter dan setter method untuk kelas Mobil untuk akses roda variabel dari luar objek. Ini bukan "Ruby cara" mendefinisikan getter dan setter; itu hanya berfungsi untuk menggambarkan apa yang getter dan setter metode yang dilakukan.
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 bekerja dan kode yang sama yang biasa digunakan untuk membuat getter dan setter metode dalam bahasa lain. Namun, Ruby menyediakan cara sederhana untuk melakukan hal ini: tiga built-in metode yang disebut attr_reader, attr_writer dan attr_acessor. Yang attr_reader metode membuat sebuah instance variabel yang dapat dibaca dari luar, attr_writer membuatnya ditulisi, dan attr_acessor membuatnya dapat dibaca dan ditulisi.
Contoh di atas dapat ditulis ulang seperti ini.
class Car
attr_accessor :wheels
end
f = Car.new
f.wheels = 4
f.wheels # Output: => 4
Dalam contoh di atas, roda atribut akan dapat dibaca dan ditulis dari luar objek. Jika bukan attr_accessor, kami menggunakan attr_reader, itu akan menjadi read-only. Jika kita menggunakan attr_writer, akan menulis saja. Tiga metode yang tidak getter dan setter dalam diri mereka sendiri tetapi, ketika dipanggil, mereka membuat getter dan setter metode untuk kami. Mereka adalah metode yang secara dinamis (pemrograman) menghasilkan metode lain; yang's disebut metaprogramming.
Pertama (lagi) misalnya, yang tidak menggunakan Ruby's built-in metode, hanya boleh digunakan ketika kode tambahan yang diperlukan dalam getter dan setter method. Misalnya, metode penyetel mungkin perlu untuk memvalidasi data atau melakukan beberapa perhitungan sebelum menetapkan nilai ke variabel contoh.
Hal ini dimungkinkan untuk mengakses (membaca dan menulis) contoh variabel dari luar objek, dengan menggunakan instance_variable_get dan instance_variable_set built-in metode. Namun, hal ini jarang dibenarkan dan biasanya ide yang buruk, seperti melewati enkapsulasi cenderung untuk melampiaskan segala macam malapetaka.
Hmmm. Banyak jawaban yang baik. Berikut adalah beberapa sen di atasnya.
attr_accessor
adalah sebuah metode sederhana yang membantu kita dalam membersihkan(KERING-ing) up mengulangi getter dan setter
metode.
Sehingga kita dapat lebih fokus pada penulisan logika bisnis dan tidak khawatir tentang setter dan getter.
Fungsi utama attr_accessor lebih dari yang lain adalah kemampuan mengakses data dari file lain. Jadi anda biasanya akan memiliki attr_reader atau attr_writer tetapi kabar baiknya adalah bahwa Ruby memungkinkan anda menggabungkan dua bersama-sama dengan attr_accessor. Saya pikir itu sebagai ku untuk pergi metode karena itu lebih baik bulat atau serbaguna. Juga, mengintip diingat bahwa di Rel, ini dihilangkan karena tidak di back-end. Jadi dengan kata lain: anda lebih baik menggunakan attr_acessor selama dua lainnya karena anda don't perlu khawatir tentang menjadi spesifik, accessor mencakup itu semua. Saya tahu ini adalah penjelasan umum tapi itu membantu saya sebagai pemula.
Harap ini membantu!