Pertanyaan Apa itu attr_accessor di Ruby?


Saya mengalami kesulitan memahami attr_accessor di Ruby. Bisakah seseorang menjelaskan ini padaku?


862
2017-12-06 21:07


asal


Jawaban:


Katakanlah Anda memiliki kelas Person.

class Person
end

person = Person.new
person.name # => no method error

Tentunya kita 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 bisa membaca namanya, tetapi itu tidak berarti kita dapat memberikan nama. Itu adalah dua metode berbeda. Yang pertama disebut pembaca dan yang terakhir disebut penulis. Kami belum membuat penulis, jadi ayo lakukan itu.

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 bisa menulis dan membaca variabel instan @name menggunakan metode pembaca dan penulis. Kecuali, ini dilakukan begitu sering, mengapa membuang 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. Ketika Anda menginginkan 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: variabel instan @name dalam 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 caranya attr_reader, attr_writer, dan attr_accessor metode sebenarnya menghasilkan metode untuk Anda, membaca jawaban lain, buku, dokumen ruby.


2046
2017-12-06 22:11



attr_accessor aku s hanya sebuah metode. (Tautan harus memberikan lebih banyak wawasan tentang cara kerjanya - lihat pasangan metode yang dihasilkan, dan tutorial harus menunjukkan cara menggunakannya.)

Triknya adalah itu class aku s bukan definisi di Ruby (itu "hanya definisi" dalam bahasa seperti C ++ dan Java), tetapi itu adalah sebuah ekspresi yang mengevaluasi. Selama evaluasi ini ketika attr_accessor metode dipanggil yang pada gilirannya memodifikasi kelas saat ini - ingat penerima implisit: self.attr_accessor, dimana self adalah objek kelas "terbuka" pada titik ini.

Kebutuhan untuk attr_accessor dan teman-teman, adalah, yah:

  1. Ruby, seperti Smalltalk, tidak mengizinkan variabel instan untuk diakses di luar metode1 untuk objek itu. Artinya, variabel instan tidak dapat diakses di x.y bentuk seperti yang biasa di katakan, Java atau bahkan Python. Di Ruby y selalu diambil sebagai pesan untuk dikirim (atau "metode untuk memanggil"). Dengan demikian attr_* metode membuat pembungkus yang proksi instance @variable akses melalui metode yang dibuat secara dinamis.

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


114
2017-12-06 21:21



attr_accessor adalah (seperti @pst menyatakan) 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 sendiri metode semacam ini 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

62
2017-12-06 21:29



attr_accessor sangat sederhana:

attr_accessor :foo

adalah pintasan untuk:

def foo=(val)
  @foo = val
end

def foo
  @foo
end

itu tidak lebih dari pengambil / penyetel untuk suatu objek


35
2017-12-06 21:28



Ini hanyalah metode yang mendefinisikan metode pengambil dan penyetel untuk variabel instan. Contoh penerapannya 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

17
2017-12-06 21:29



Pada dasarnya mereka palsu atribut data yang dapat diakses publik, yang tidak memiliki Ruby.


16
2017-12-06 21:11



Saya menghadapi masalah ini juga dan menulis jawaban yang agak panjang untuk pertanyaan ini. Ada beberapa jawaban yang bagus tentang hal ini, tetapi siapa pun yang mencari klarifikasi lebih lanjut, saya harap jawaban saya dapat membantu

Inisialisasi Metode

Inisialisasi memungkinkan Anda untuk mengatur data ke instance objek saat membuat instance daripada harus menetapkannya pada baris terpisah di kode Anda setiap kali Anda membuat instance baru dari kelas.

class Person
  attr_accessor :name

  def initialize(name)
    @name = name
  end


  def greeting
    "Hello #{@name}"
  end
end

person = Person.new("Denis")
puts person.greeting

Dalam kode di atas kami menetapkan nama "Denis" menggunakan metode inisialisasi dengan melewati Dennis melalui parameter di Initialize. 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, kami menetapkan nama dengan memanggil metode attr_accessor setter menggunakan person.name, daripada menetapkan nilai setelah inisialisasi objek.

Kedua "metode" melakukan pekerjaan ini, tetapi menginisialisasi menghemat waktu dan baris kode.

Ini adalah satu-satunya pekerjaan menginisialisasi. Anda tidak dapat memanggil inisialisasi sebagai metode. Untuk benar-benar mendapatkan nilai objek instance, 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, Setters (attr_reader, attr_writer, attr_accessor)

Getters, attr_reader: Seluruh tujuan pengambil adalah mengembalikan nilai dari variabel instan tertentu. Kunjungi kode contoh di bawah ini untuk rincian tentang 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 "nama_produk" dan "kuantitas" pada contoh Item "contoh". "Puts example.item_name" dan "example.quantity" akan mengembalikan (atau "mendapatkan") nilai untuk parameter yang dilewatkan ke dalam "contoh" dan menampilkannya ke layar.

Untungnya di Ruby ada metode inheren yang memungkinkan kita untuk menulis kode ini 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 dengan menyimpan enam baris kode. Bayangkan jika Anda memiliki 5 negara lebih disebabkan ke kelas Item? Kode akan lama cepat.

Setter, attr_writer: Apa yang melintas saya pada awalnya dengan metode setter adalah bahwa di mata saya tampaknya melakukan fungsi yang identik dengan metode inisialisasi. Di bawah ini saya jelaskan perbedaannya berdasarkan pemahaman saya;

Sebagaimana dinyatakan sebelumnya, metode inisialisasi memungkinkan Anda untuk menetapkan nilai untuk sebuah instance dari objek pada pembuatan objek.

Tetapi bagaimana jika Anda ingin mengatur nilainya nanti, setelah instance dibuat, atau mengubahnya setelah diinisialisasi? Ini akan menjadi skenario di mana Anda akan menggunakan metode setter. ITULAH PERBEDAANNYA. Anda tidak perlu "mengatur" keadaan tertentu saat Anda menggunakan metode attr_writer pada awalnya.

Kode di bawah ini adalah contoh penggunaan metode penyetel untuk menyatakan nilai item_name untuk instance ini dari kelas Item. Perhatikan bahwa kami terus menggunakan metode pengambil attr_reader sehingga kami bisa mendapatkan nilai dan mencetaknya ke layar, kalau-kalau Anda ingin menguji kode 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 merupakan pengulangan dari contoh inisialisasi di atas di mana kita menggunakan inisialisasi untuk menetapkan nilai objek dari nama_produk pada saat pembuatan.

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: Menjalankan fungsi dari attr_reader dan attr_writer, menghemat satu baris kode lagi.


12
2017-09-16 01:03