Apa attr_accessor di Ruby?

Saya mengalami waktu yang sulit memahami attr_accessor di Ruby. Seseorang dapat menjelaskan hal ini kepada saya?

Mengomentari pertanyaan (3)
Larutan

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.

Komentar (32)

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:

  1. 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.

  2. 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.

Komentar (2)

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
Komentar (3)

attr_accessor adalah sangat sederhana:

attr_accessor :foo

adalah jalan pintas untuk:

def foo=(val)
  @foo = val
end

def foo
  @foo
end

hal ini tidak lebih dari sebuah getter/setter untuk sebuah objek

Komentar (2)

Pada dasarnya mereka palsu yang dapat diakses publik data atribut, yang Ruby doesn't memiliki.

Komentar (3)

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
Komentar (1)

Penjelasan Sederhana Tanpa Kode

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

  • Let's membayangkan benar-benar rahasia tempat: CIA. Tidak ada yang tahu apa yang's terjadi di CIA terpisah dari orang-orang di dalam CIA. Dengan kata lain, orang luar tidak dapat mengakses informasi apapun di CIA. Tapi karena itu's tidak ada gunanya memiliki sebuah organisasi yang benar-benar rahasia, informasi tertentu yang dibuat tersedia untuk dunia luar - satunya hal bahwa CIA ingin semua orang tahu tentang tentu saja: misalnya Direktur CIA, cara ramah lingkungan departemen ini dibandingkan dengan semua departemen pemerintah lainnya dll. Informasi lainnya: misalnya yang bersifat rahasia koperasi di Irak atau Afghanistan - jenis hal-hal yang mungkin akan tetap menjadi rahasia selama 150 tahun ke depan.
  • 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

  • Di sisi lain, jika anda sudah dalam CIA, maka anda bisa dengan mudah menghubungi anda agen CIA di Kabul karena informasi ini dapat diakses dengan mudah mengingat anda sudah dalam. Tapi jika anda're luar CIA, anda hanya tidak akan diberikan akses: anda tidak akan bisa tahu siapa mereka (baca access), dan anda tidak akan mampu mengubah misi mereka (tulis).

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.

Komentar (4)

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"
Komentar (1)

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.

Komentar (0)

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.

Komentar (0)

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.

Komentar (0)

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
Komentar (0)

Hanya attr-accessor menciptakan pengambil dan setter metode untuk atribut tertentu

Komentar (0)

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=]
Komentar (0)

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

Komentar (0)

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
Komentar (0)

Atribut dan metode pengakses

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 #

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.

Komentar (0)

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.

Komentar (0)

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!

Komentar (0)