Apa itu attr_accessor di Ruby?

1024

Saya mengalami kesulitan memahami attr_accessordi Ruby .
Adakah yang bisa menjelaskan hal ini kepada saya?

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

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 @namemenggunakan 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 @namedi 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_writerdan attr_accessormetode sebenarnya menghasilkan metode untuk Anda, baca jawaban lain, buku, dokumen ruby.

Max Chernyak
sumber
46
@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:

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

  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 instance publik".

Komunitas
sumber
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:

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
Phrogz
sumber
3
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
end

def foo
  @foo
end

itu tidak lebih dari pengambil / penyetel untuk suatu objek

efalcao
sumber
10
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.

Tyler Eaves
sumber
4
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:

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
Membuang
sumber
menangani banyak atribut dengan cara ini hebat!
Wasif Hossain
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.

BKSpurgeon
sumber
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

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"
Ahmed Eshaan
sumber
2
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.

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.

Jbur43
sumber
10

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.

Ben
sumber
7

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.

Marcus Thornton
sumber
5

Cukup attr-accessormembuat getterdan settermetode untuk atribut yang ditentukan

Veeru
sumber
5

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

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.

$ bankie.balance
$ bankie.owner
Iggy
sumber
2

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=]
Praveen_Shukla
sumber
1

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

Douglas G. Allen
sumber
1

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
Adverbia
sumber
0

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.

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.

BrunoFacca
sumber
-2

Hmmm. Banyak jawaban bagus. Ini beberapa sen saya di atasnya.

  • attr_accessoradalah 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.

Abibullah Rahamathulah
sumber
-3

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!

creativegeek
sumber