Ruby'de attr_accessor nedir?


1023

Ben çok zor günler anlama yaşıyorum attr_accessoryılında Ruby .
Birisi bana bunu açıklayabilir mi?



1
Attr_accessor Git'te de aynı şekilde çalışıyor mu? Bazı eğiticilerin yeterince açıklama yapmadığını, bazılarının da önceden bilgi sahibi olduğunu düşünüyorum.
Angelfirenze

10
@Angelfirenze, gitonunla hiçbir ilgisi yok attr_accessor. Git bir sürüm kontrol yazılımı iken Ruby'deattr_accessor bir yöntemdir .
Özbekjon

Yanıtlar:


2360

Diyelim ki bir dersiniz var Person.

class Person
end

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

Açıkçası yöntemi hiç tanımlayamadık name. Hadi bunu yapalım.

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, ismi okuyabiliriz, ama bu ismi atayabileceğimiz anlamına gelmez. Bunlar iki farklı yöntem. İlki okuyucu , ikincisi yazar olarak adlandırılır . Yazarı henüz yaratmadık, hadi yapalım.

class Person
  def name
    @name
  end

  def name=(str)
    @name = str
  end
end

person = Person.new
person.name = 'Dennis'
person.name # => "Dennis"

Muhteşem. Şimdi @nameokuyucu ve yazıcı yöntemlerini kullanarak örnek değişkeni yazıp okuyabiliriz . Dışında, bu çok sık yapılır, neden her zaman bu yöntemleri yazmak için zaman harcamak? Bunu daha kolay yapabiliriz.

class Person
  attr_reader :name
  attr_writer :name
end

Bu bile tekrarlanabilir. Hem okuyucu hem de yazar istediğiniz zaman sadece erişimci kullanın!

class Person
  attr_accessor :name
end

person = Person.new
person.name = "Dennis"
person.name # => "Dennis"

Aynı şekilde çalışır! Ve bilin bakalım: @namebizim nesne nesnemizdeki örnek değişkeni , bunu manuel olarak yaptığımız gibi ayarlanacaktır, böylece diğer yöntemlerde kullanabilirsiniz.

class Person
  attr_accessor :name

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

person = Person.new
person.name = "Dennis"
person.greeting # => "Hello Dennis"

Bu kadar. Nasıl anlamak için attr_reader, attr_writerve attr_accessordiğer cevaplar, kitaplar, yakut dokümanlar, yöntemler aslında sizin için yöntemler üretmek okuyun.


46
@hakunin - bu net cevap için teşekkür ederim. Benim için eksik olan şey, Ruby sözdiziminin attr_ * ifadesindeki örnek değişkenler için iki nokta üst üste ':' önerdiğidir? Değişkene atıfta bulunmak için sınıfın başka bir yerinde kullanılan aynı '@' sözdizimini kullanmak daha kolay olacaktır.
Will

207
@WilliamSmith Sorunuzu yanıtlamak için attr_accessorbunun geçerli sınıfta çağrılan bir yöntem olduğunu ve bu yönteme ilettiğiniz :namebir parametre olduğunu anlamanız gerekir . Özel bir sözdizimi değil, basit bir yöntem çağrısı. Eğer @namedeğişken verirseniz , mantıklı olmazdı, çünkü @name içerecektir nil. Yani yazmak gibi olurdu attr_accessor nil. Oluşturması gereken bir değişkeni değil, değişkenin çağrılmasını istediğiniz adı geçiyorsunuz.
Max Chernyak

23
@hakunin - Bu tamamen mantıklı. Ben sadece yakut bir dosya üzerinden ayrıştırırken aslında 'çalışıyor' olduğunu ve her ifade ve ifade aslında bazı nesne üzerinde bir yöntem çağrısı olduğunu öğrendim. Attr_accessor dahil. Çok yararlı.
Will

52
Rails'i 3 yıl boyunca kullandım, bunu bile bilmiyordum. Utanç
Sean Xiao

5
@Buminda evet, ancak yöntem nameve değişken @nameaynı şey değil. Onları karıştırmayın. @nameSınıfınızda örnek değişkeniniz var ve bunu attr_reader :namedışarıdan okuyabileceğinizi tanımlıyorsunuz . attr_readerBasit bir yol olmadan @namesınıfınızın dışına erişebilirsiniz .
Max Chernyak

127

attr_accessor olduğu bir yöntem . (Bağlantı, nasıl çalıştığı hakkında daha fazla bilgi sağlamalıdır - oluşturulan yöntem çiftlerine bakın ve bir eğitici size nasıl kullanılacağını göstermelidir.)

Hile olduğunu classolduğunu bir tanım değil (o C ++ ve Java gibi dillerde "sadece bir tanım" dır) Ruby, ancak bir olduğunu değerlendirir olduğunu ifade . Bu değerlendirme sırasında attr_accessoryöntem çağrıldığında geçerli sınıfı değiştirir - örtülü alıcıyı hatırlayın: bu noktada "açık" sınıf nesnesi self.attr_accessornerede self.

attr_accessorVe arkadaşlara olan ihtiyaç , iyi:

  1. Ruby, Smalltalk gibi, örnek değişkenlerine o nesne için yöntemler 1 dışında erişilmesine izin vermez . Yani, örneğin x.yJava veya Python'da yaygın olan örnek değişkenlere formda erişilemez . Ruby yher zaman göndermek için bir mesaj olarak alınır (veya "aramak için yöntem"). Böylece attr_*yöntemler @variable, dinamik olarak oluşturulan yöntemler aracılığıyla örneğin erişimini proxy yapan sarmalayıcılar oluşturur.

  2. Ortak berbat

Umarım bu bazı küçük ayrıntıları açıklar. Mutlu kodlama.


1 Bu kesinlikle doğru değildir ve bunun etrafında bazı "teknikler" vardır, ancak "genel örnek değişkeni" erişimi için sözdizimi desteği yoktur.


Attr_accessor "sadece bir yöntem" olduğunu söylediğimde anladım. Ancak bu yöntemi çağırmak için kullanılan sözdizimi nedir? Ruby_ Belgeleri sözdiziminden bahsetmiş olan some_method: name => "whatever",: notherName,: etc
BT

68

attr_accessor(@pst'nin belirttiği gibi) sadece bir yöntemdir. Yaptığı şey sizin için daha fazla yöntem yaratmaktır.

Yani buradaki kod:

class Foo
  attr_accessor :bar
end

bu koda eşdeğerdir:

class Foo
  def bar
    @bar
  end
  def bar=( new_value )
    @bar = new_value
  end
end

Bu tür bir yöntemi Ruby'de kendiniz yazabilirsiniz:

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

3
Bu, en yeni düzey senaryolarında bile meta programlamanın kullanıldığı harika bir örnektir. Çok hoş.
John Simon

2
attr_accessorSonunda bir uygulama taslağı arıyordum ve buldum! Sorunumu çözmesine rağmen, bunun gibi bir uygulama örneğini nerede bulabileceğimi merak ediyorum (kitap / resmi doktor)?
Wasif Hossain

40

attr_accessor çok basit:

attr_accessor :foo

şunun için bir kısayoldur:

def foo=(val)
  @foo = val
end

def foo
  @foo
end

bir nesne için bir alıcı / ayarlayıcıdan başka bir şey değildir


10
cevabınız iyi. 'Kısayol', sözlüğüme göre "sözdizimi şekeri" veya "yorumlayıcı tarafından yorumlanan makro" değil, "daha kısa bir alternatif yol" anlamına gelir.
bowsersenior

25

Temelde, Ruby'nin sahip olmadığı halka açık veri özelliklerini taklit ediyorlar.


4
Bu yorum tamamen yararlı olmasa da, doğrudur. Genel veri özniteliklerinin Ruby'deki "get" yöntemlerinin dışında bulunmadığı gerçeğini vurgular; bu, dili öğrenmeye çalışan biri için gerçekten yararlı bir bilgidir.
Eric Dand

3
Bu gerçekten önemsenmemelidir. Ruby olmayan bir adam bu şeyleri anlamaya çalışırken, bu cevap çok yararlı!
Brad

1
Kabul etti, C # 'ın adına çok benziyor {get; set;}
David Miler

17

Yalnızca örnek değişkenler için alıcı ve ayarlayıcı yöntemlerini tanımlayan bir yöntemdir. Örnek bir uygulama:

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

birden çok özelliği bu şekilde kullanmak harika!
Wasif Hossain

Bu, meta programlamayla ilgili başka bir soruyu çözmek için gerçekten yararlı bir kod snippet'iydi.
alexventuraio

15

Herhangi Bir Kod Olmadan Basit Açıklama

Yukarıdaki cevapların çoğunda kod kullanılır. Bu açıklama, bir benzetme / hikaye kullanarak, hiç kullanmadan cevaplamaya çalışır:

Dış taraflar dahili CIA sırlarına erişemez

  • Gerçekten gizli bir yer düşünelim: CIA. CIA içindeki insanlar dışında CIA'da neler olduğunu kimse bilmiyor. Başka bir deyişle, dış kişiler CIA'daki hiçbir bilgiye erişemez. Ancak tamamen gizli bir organizasyona sahip olmanın iyi olmadığı için, dış dünyaya belirli bilgiler sunulur - sadece CIA'nın herkesin elbette bilmesini istediği şeyler: örneğin CIA Direktörü, bu bölümün çevre dostu karşılaştırması Diğer bilgiler: örneğin Irak veya Afganistan'daki gizli ajanları kimdir - bu tür şeyler önümüzdeki 150 yıl boyunca muhtemelen bir sır olarak kalacaktır.

  • CIA dışındaysanız, yalnızca herkese açık hale getirdiği bilgilere erişebilirsiniz. Veya CIA parlance özelliğini kullanmak için yalnızca "temizlenmiş" bilgilere erişebilirsiniz.

  • CIA'nın CIA dışındaki genel halka sunmak istediği bilgilere şunlar denir: özellikler.

Okuma ve yazma özelliklerinin anlamı:

  • CIA söz konusu olduğunda, çoğu özellik "salt okunur" dur. Eğer bir taraf varsa bu araçlar dış CIA'ya yapabilirsiniz soruyorum: "Kim CIA direktörü nedir?" ve doğrudan bir cevap alacaksınız. Ama ne edemez ilgisi özelliklerini "salt okunur" CIA değişiklikler değişiklikleri yapmaktır. örneğin bir telefon görüşmesi yapamaz ve birden Kim Kardashian'ın Yönetmen olmasını veya Paris Hilton'un Başkomutan olmasını istediğinize karar veremezsiniz .

  • Öznitelikler size "yazma" erişimi verdiyse, dışarıda olsanız bile, isterseniz değişiklik yapabilirsiniz. Aksi takdirde, yapabileceğiniz tek şey okumaktır.

    Başka bir deyişle, erişimciler, erişimcilerin okuma veya yazma erişimcileri olmasına bağlı olarak, harici kişilerin içeri girmesine izin vermeyen kuruluşlarda soruşturma yapmanıza veya değişiklik yapmanıza izin verir.

Sınıf içindeki nesneler kolayca birbirine erişebilir

  • Öte yandan, zaten CIA içindeyseniz , Kabil'deki CIA operatörünüzü kolayca çağırabilirsiniz, çünkü zaten içerideyseniz bu bilgilere kolayca erişilebilir. Ancak CIA dışındaysanız , size erişim izni verilmeyecektir: kim olduklarını bilemeyeceksiniz (okuma erişimi) ve görevlerini değiştiremeyeceksiniz (yazma erişimi).

Sınıflar ve değişkenler, özellikler ve içindeki metodlara erişebilmeniz için tam olarak aynı şey. HTH! Herhangi bir sorunuz varsa, lütfen sorun ve umarım netleştirebilirim.


Açıklamanız mantıklı! +1 Maalesef, CIA tarafından temizlenen bilgilerin doğru olduğundan emin misiniz?
kouty

CIA'da çeşitli "boşluk" seviyeleri vardır: örneğin, Top Secret (Prez dışında kimse) veya kamu güveni (herkes bu bilgiyi okuyabilir). CIA aslında çok güzel gerçekler sunuyor!
BKSpurgeon

Sadece Kardashian, Paris Hilton örnekleri için upvote hak ediyorsunuz :) Başkan için Trump ile yeterince kötü olduğunu düşündüm, bu iki sorumlu omg hayal!
rmcsharry

Evet! İhtiyacımız olan bu, kodsuz StackOverflow! :-)
Marvin

13

OOP konseptine aşina iseniz, alıcı ve ayarlayıcı yöntemine aşina olmalısınız. attr_accessor Ruby'de de aynısını yapar.

Getter ve Setter Genel Yol

class Person
  def name
    @name
  end

  def name=(str)
    @name = str
  end
end

person = Person.new
person.name = 'Eshaan'
person.name # => "Eshaan"

Setter Yöntemi

def name=(val)
  @name = val
end

Getter yöntemi

def name
  @name
end

Ruby'de Getter ve Setter yöntemi

class Person
  attr_accessor :name
end

person = Person.new
person.name = "Eshaan"
person.name # => "Eshaan"

2
mükemmel bir açıklama! Çok kullanışlı bir davranıştır ve çok kolay bir şekilde geçersiz kılınabilir.
Rubyrider

12

Bu sorunla da karşılaştım ve bu soruya biraz uzun bir cevap yazdım. Bu konuda zaten bazı harika cevaplar var, ancak daha fazla açıklama isteyen herkes, umarım cevabım yardımcı olabilir

Sıfırlama Yöntemi

Initialize, sınıfın her yeni örneğini oluşturduğunuzda bunları kodunuzda ayrı bir satıra ayarlamak yerine, örneğin oluşturulduktan sonra bir nesnenin örneğine ayarlamanızı sağlar.

class Person

  def initialize(name)
    @name = name
  end


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

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

Yukarıdaki kodda Dennis'i Initialize parametresinden geçirerek initialize yöntemini kullanarak “Denis” adını ayarlıyoruz. Başlatma yöntemi olmadan adı ayarlamak istersek şöyle yapabilirdik:

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

Yukarıdaki kodda, nesneyi başlattıktan sonra değerleri ayarlamak yerine person.name kullanarak attr_accessor setter yöntemini çağırarak adı ayarladık.

Her ikisi de bu işi yapmak için "yöntemler", ancak başlat bize zaman ve kod satırları kazandırır.

Bu ilk başlatma işidir. Bir yöntem olarak başlatma işlemini çağıramazsınız. Bir örnek nesnesinin değerlerini almak için getters ve setters (kullanmanız gerekir) (attr_reader (get), attr_writer (set) ve attr_accessor (her ikisi)). Bunlar hakkında daha fazla ayrıntı için aşağıya bakın.

Getters, Setters (Attr_reader, attr_writer, attr_accessor)

Getters, attr_reader: Bir alıcının amacı, belirli bir örnek değişkeninin değerini döndürmektir. Bununla ilgili bir döküm için aşağıdaki örnek kodu ziyaret edin.

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

Yukarıdaki kodda, "örnek" öğesinin örneğinde "öğe_adı" ve "miktar" yöntemlerini çağırıyorsunuz. “Example.item_name” koyar ve “example.quantity”, “örnek” e aktarılan parametrelerin değerini döndürür (veya “al”) ve bunları ekranda görüntüler.

Neyse ki Ruby'de bu kodu daha özlü bir şekilde yazmamızı sağlayan doğal bir yöntem var; attr_reader yöntemi. Aşağıdaki koda bakın;

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

Bu sözdizimi aynı şekilde çalışır, sadece bize altı satır kod kazandırır. Item sınıfına atfedilebilecek 5 durumunuz daha var mı? Kod hızla uzayacaktır.

Setters, attr_writer: Beni ilk olarak setter yöntemleriyle geçen şey, gözlerimde başlatma yöntemine özdeş bir işlev yerine getirmiş gibi görünüyor. Aşağıda, anlayışım temelinde farkı açıklarım;

Daha önce belirtildiği gibi, initialize yöntemi, nesne oluşturulduktan sonra bir nesnenin bir örneği için değerleri ayarlamanıza olanak tanır.

Ancak, değerleri daha sonra, örnek oluşturulduktan sonra ayarlamak veya başlatıldıktan sonra değiştirmek isterseniz ne olur? Bu, bir ayarlayıcı yöntemi kullanacağınız bir senaryodur. FARK YARATIR. Başlangıçta attr_writer yöntemini kullanırken belirli bir durumu “ayarlamanız” gerekmez.

Aşağıdaki kod, Item sınıfının bu örneği için item_name değerini bildirmek üzere bir ayarlayıcı yönteminin kullanımına bir örnektir. Kodu kendi başınıza test etmek istemeniz durumunda, değerleri almak ve bunları ekrana yazdırmak için attr_reader getter yöntemini kullanmaya devam ettiğimize dikkat edin.

class Item

attr_reader :item_name

  def item_name=(str)
    @item_name = (str)
  end

end

Aşağıdaki kod, kodumuzu bir kez daha kısaltmak ve bize zaman kazandırmak için attr_writer kullanımına bir örnektir.

class Item

attr_reader :item_name
attr_writer :item_name

end

item = Item.new
puts item.item_name = "TV"

Aşağıdaki kod, oluşturma sırasında item_name öğesinin nesne değerini ayarlamak için initialize komutunu kullandığımız yukarıdaki başlatma örneğinin yinelenmesidir.

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: Hem attr_reader hem de attr_writer işlevlerini gerçekleştirerek size bir kod satırı daha kaydeder.


10

Yeni Rubyistleri / programcıları (benim gibi) karıştırmanın bir parçası olduğunu düşünüyorum:

"Neden sadece herhangi bir özelliğe (örneğin, ad) sahip olduğunu söyleyemiyorum ve bu özelliğe tek bir geçişte bir değer veremiyorum?"

Biraz daha genelleştirilmiş, ama benim için bu şekilde tıkladı:

Verilen:

class Person
end

Kişiyi, bu konu için bir adı veya başka nitelikleri olabilecek bir şey olarak tanımlamıyoruz .

O zaman eğer:

baby = Person.new

... ve onlara bir isim vermeye çalışın ...

baby.name = "Ruth"

Bir hata alırız, çünkü Rubyland'da, bir Person sınıfı nesnesi henüz bir "isim" ile ilişkilendirilmiş veya sahip olabilen bir şey değildir ...!

AMA verilen yöntemlerden herhangi birini kullanabiliriz (önceki yanıtlara bakınız), "Bir Person sınıfının ( baby) örneğinin artık " name "adında bir niteliği olabilir , bu nedenle yalnızca sözdizimsel bir ancak bu ismi almamız mantıklı. "

Yine, bu soruyu biraz daha farklı ve daha genel bir açıdan vurmak, ancak umarım bu, bu konuya giden yolu bulan Sınıf Personeli'nin bir sonraki örneğine yardımcı olur.


7

Basitçe söylemek gerekirse, sınıf için bir ayarlayıcı ve alıcı tanımlayacaktır.

Bunu not et

attr_reader :v is equivalant to 
def v
  @v
end

attr_writer :v is equivalant to
def v=(value)
  @v=value
end

Yani

attr_accessor :v which means 
attr_reader :v; attr_writer :v 

sınıf için bir ayarlayıcı ve alıcı tanımlamak için eşdeğerdir.


5

Belirtilen öznitelikler için ve yöntemlerini basitçe attr-accessoroluştururgettersetter


5

Bunu anlamanın bir başka yolu da sahip olduğu hata kodunu ortadan kaldırmaktır attr_accessor.

Misal:

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

Aşağıdaki yöntemler kullanılabilir:

$ bankie = BankAccout.new("Iggy")
$ bankie 
$ bankie.deposit(100)
$ bankie.withdraw(5)

Aşağıdaki yöntemler hata verir:

$ bankie.owner     #undefined method `owner'... 
$ bankie.balance   #undefined method `balance'...

ownerve balanceteknik olarak bir yöntem değil, bir özniteliktir. BankAccount sınıfında def ownerve yoktur def balance. Varsa, aşağıdaki iki komutu kullanabilirsiniz. Ama bu iki yöntem yok. Ancak, olabilir erişmek sen olsaydın gibi nitelikleri erişmek aracılığıyla bir yöntem attr_accessor!! Dolayısıyla kelimeattr_accessor . Özellik. Erişimci. Bir yönteme eriştiğiniz gibi özniteliklere erişir.

Ekleme attr_accessor :balance, :owner, okuma ve yazma balanceve owner"yöntem" sağlar. Şimdi son 2 yöntemi kullanabilirsiniz.

$ bankie.balance
$ bankie.owner

2

Bu modül için adlandırılmış bir öznitelik tanımlar; burada ad symbol.id2name'dir, bir örnek değişkeni (@name) ve bunu okumak için karşılık gelen bir erişim yöntemi oluşturur. Ayrıca özniteliği ayarlamak için name = adlı bir yöntem oluşturur.

module Mod
  attr_accessor(:one, :two)
end
Mod.instance_methods.sort   #=> [:one, :one=, :two, :two=]

1

Bir özellik erişimcisini özetlemek gerekirse aka attr_accessor size iki ücretsiz yöntem sunar.

Java'da olduğu gibi getters ve setters olarak adlandırılırlar.

Birçok cevap iyi örnekler gösterdi, bu yüzden sadece kısa olacağım.

#the_attribute

ve

# The_attribute =

Eski yakut dokümanlarda bir karma etiketi # bir yöntem anlamına gelir. Ayrıca bir sınıf adı öneki de içerebilir ... MyClass # my_method


1

Yakutta yeniyim ve sadece aşağıdaki garipliği anlamakla uğraşmak zorunda kaldım. Gelecekte başka birine yardım edebilir. Sonunda yukarıda belirtildiği gibi, 2 fonksiyonun (def myvar, def myvar =) ikisi de @myvar'a erişmek için dolaylı olarak elde edilir, ancak bu yöntemler yerel bildirimlerle geçersiz kılınabilir.

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

0

Özellikler ve erişimci yöntemleri

Öznitelikler, nesnenin dışından erişilebilen sınıf bileşenleridir. Diğer birçok programlama dilinde özellik olarak bilinirler. Değerlerine object_name.attribute_name'deki gibi "nokta gösterimi" kullanılarak erişilebilir. Python ve diğer birkaç dilden farklı olarak, Ruby örnek değişkenlerine doğrudan nesnenin dışından erişilmesine izin vermez.

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>

Yukarıdaki örnekte, c, Car sınıfının bir örneğidir (nesnesidir). Tekerlek örneği değişkeninin değerini nesnenin dışından okumaya çalıştık. Olan şey, Ruby'nin c nesnesi içinde tekerlekler adlı bir yöntemi çağırmaya çalışmasıydı, ancak böyle bir yöntem tanımlanmadı. Kısacası, object_name.attribute_name nesne içinde attribute_name adlı bir yöntemi çağırmaya çalışır. Tekerlek değişkeninin değerine dışarıdan erişmek için, bu ada göre çağrıldığında bu değişkenin değerini döndürecek bir örnek yöntemi uygulamamız gerekir. Buna erişimci yöntemi denir. Genel programlama bağlamında, bir örnek değişkenine nesnenin dışından erişmenin genel yolu, alıcı ve ayarlayıcı yöntemleri olarak da bilinen erişimci yöntemlerini uygulamaktır.

Aşağıdaki örnekte, tekerlek değişkenine nesnenin dışından erişmek için Araba sınıfına alıcı ve ayarlayıcı yöntemleri ekledik. Bu, alıcıları ve belirleyicileri tanımlamanın “yakut yolu” değildir; yalnızca alıcı ve ayarlayıcı yöntemlerinin ne yaptığını göstermeye yarar.

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

Yukarıdaki örnek işler ve benzer kod, diğer dillerde alıcı ve ayarlayıcı yöntemleri oluşturmak için yaygın olarak kullanılır. Bununla birlikte, Ruby bunu yapmak için daha basit bir yol sağlar: attr_reader, attr_writer ve attr_acessor adlı üç yerleşik yöntem. Attr_reader yöntemi, bir örnek değişkenini dışarıdan okunabilir yapar, attr_writer bunu yazılabilir yapar ve attr_acessor onu okunabilir ve yazılabilir yapar.

Yukarıdaki örnek bu şekilde yeniden yazılabilir.

class Car
  attr_accessor :wheels
end

f = Car.new
f.wheels = 4
f.wheels  # Output: => 4

Yukarıdaki örnekte, tekerlekler özelliği nesnenin dışından okunabilir ve yazılabilir olacaktır. Eğer attr_accessor yerine attr_reader kullanırsak, salt okunur olur. Eğer attr_writer kullansaydık, salt yazılır. Bu üç yöntem kendi içinde alıcılar ve ayarlayıcılar değildir, ancak çağrıldıklarında bizim için alıcı ve ayarlayıcı yöntemler oluştururlar. Bunlar dinamik olarak (programlı olarak) başka yöntemler üreten yöntemlerdir; buna metaprogramlama denir.

Ruby'nin yerleşik yöntemlerini kullanmayan ilk (daha uzun) örnek yalnızca alıcı ve ayarlayıcı yöntemlerinde ek kod gerektiğinde kullanılmalıdır. Örneğin, bir ayarlayıcı yönteminin bir örnek değişkenine bir değer atamadan önce verileri doğrulaması veya bir miktar hesaplama yapması gerekebilir.

İnstance_variable_get ve instance_variable_set yerleşik yöntemlerini kullanarak örnek değişkenlere nesne dışından erişmek (okumak ve yazmak) mümkündür. Bununla birlikte, bu nadiren haklı görülebilir ve genellikle kötü bir fikirdir, çünkü kapsüllemeyi atlamak her türlü tahribatı bozma eğilimindedir.


-2

Hmmm. Çok iyi cevaplar. İşte birkaç sentim.

  • attr_accessoryinelenen yöntemleri temizlememize ( DRY-ing ) yardımcı olan basit bir yöntemdir .getter and setter

  • Böylece daha çok iş mantığı yazmaya odaklanabiliriz ve pasifler ve alıcılar için endişelenmeyiz.


-3

Attr_accessor'un diğer işlevler üzerindeki ana işlevi, diğer dosyalardan verilere erişebilmesidir.
Yani genellikle attr_reader veya attr_writer olurdu ama iyi haber şu ki Ruby bu ikisini attr_accessor ile birleştirmenize izin veriyor. Benim gitme yöntemi olarak düşünüyorum çünkü daha iyi yuvarlak veya çok yönlü. Ayrıca, Rails'te bunun ortadan kaldırıldığından, bunun sizin için arka uçta yaptığını unutmayın. Diğer bir deyişle: diğer ikisine göre attr_acessor kullanmaktan daha iyidir, çünkü spesifik olmak için endişelenmenize gerek yoktur, erişimci her şeyi kapsar. Bunun genel bir açıklama olduğunu biliyorum ama yeni başlayanlar için bana yardımcı oldu.

Umarım bu yardımcı oldu!

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.