配列 - ruby attr_reader




Rubyのattr_accessorとは何ですか? (12)

属性とアクセサメソッド

属性は、オブジェクトの外部からアクセスできるクラスコンポーネントです。 それらは、他の多くのプログラミング言語のプロパティとして知られています。 それらの値はobject_name.attribute_nameのように "ドット表記法"を使ってアクセスできます。 Pythonや他のいくつかの言語とは異なり、Rubyではインスタンス変数がオブジェクトの外部から直接アクセスされることはありません。

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>

上記の例では、cはCarクラスのインスタンス(オブジェクト)です。 ホイールのインスタンス変数の値をオブジェクトの外側から読み取ろうとして失敗しました。 何が起こったのは、Rubyがcオブジェクト内のwheelという名前のメソッドを呼び出そうとしましたが、そのようなメソッドは定義されていませんでした。 つまり、object_name.attribute_nameは、オブジェクト内のattribute_nameという名前のメソッドを呼び出そうとします。 車輪変数の値に外部からアクセスするには、その名前でインスタンスメソッドを実装する必要があります。このメソッドは、呼び出されたときにその変数の値を返します。 これをアクセサメソッドと呼びます。 一般的なプログラミングのコンテキストでは、オブジェクトの外部からインスタンス変数にアクセスする通常の方法は、getterメソッドとsetterメソッドとも呼ばれるアクセサメソッドを実装することです。 ゲッターは、クラス内で定義された変数の値を外部から読み取ることを可能にし、セッターはそれを外部から書き込むことを可能にします。

次の例では、getterメソッドとsetterメソッドをCarクラスに追加して、オブジェクトの外側からwheels変数にアクセスしました。 getterとsetterを定義する "Rubyの方法"ではありません。 getterメソッドとsetterメソッドが何をするかを説明するためだけに役立ちます。

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

上記の例は動作し、他の言語でgetterとsetterメソッドを作成するために、同様のコードが一般的に使用されます。 しかし、Rubyはこれを行うための簡単な方法を提供しています:attr_reader、attr_writer、attr_acessorという3つの組み込みメソッド。 attr_readerメソッドは、外部からインスタンス変数を読み取り可能にし、attr_writerは書き込み可能にし、attr_acessorは読み書き可能にします。

このように上記の例を書き換えることができます。

class Car
  attr_accessor :wheels
end

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

上の例では、wheels属性はオブジェクトの外部から読み書き可能です。 attr_accessorの代わりにattr_readerを使用した場合、読み取り専用になります。 attr_writerを使用すると、書き込み専用になります。 これらの3つのメソッドはゲッターとセッターではありませんが、呼び出されるとゲッターメソッドとセッターメソッドが作成されます。 これらは、他のメソッドを動的に(プログラム的に)生成するメソッドです。 それはメタプログラミングと呼ばれています。

Rubyの組み込みメソッドを使用しない最初の(もっと長い)例は、getterメソッドとsetterメソッドで追加のコードが必要な場合にのみ使用してください。 たとえば、インスタンス変数に値を代入する前に、セッターメソッドでデータの検証や計算を行う必要があるかもしれません。

instance_variable_getおよびinstance_variable_set組み込みメソッドを使用すると、オブジェクトの外部からインスタンス変数にアクセス(読み書き)することができます。 しかし、カプセル化を迂回することはあらゆる種類の混乱を招く傾向があるため、これはまれに正当化され、通常は悪い考えです。

私はRubyでattr_accessorを理解するのに苦労しています。 誰かが私にこれを説明することはできますか?


attr_accessorという属性アクセサを要約すると、2つの方法があります。

Javaの場合と同様に、getterやsetterと呼ばれます。

多くの答えが良い例を示しているので、私は簡単にするつもりです。

#the_attribute

そして

#the_attribute =

古いルビドキュメントでは、ハッシュタグ#はメソッドを意味します。 また、クラス名の接頭辞を含むことができます... MyClass#my_method


attr_accessorは非常に簡単です:

attr_accessor :foo

次のショートカットです:

def foo=(val)
  @foo = val
end

def foo
  @foo
end

オブジェクトのゲッター/セッター以上のものではありません


attr_accessorは(@ pstが述べたように)単なるメソッドです。 それがしていることは、あなたのためのより多くの方法を作成することです。

このコードはここにあります:

class Foo
  attr_accessor :bar
end

このコードに相当します:

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

この種のメソッドを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

あなたがOOPの概念に精通しているなら、ゲッターとセッターメソッドに精通している必要があります。 attr_accessorはRubyでも同じことをします。

ゲッターとセッター

class Person
  def name
    @name
  end

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

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

セッターメソッド

def name=(val)
  @name = val
end

ゲッター法

def name
  @name
end

Rubyのゲッターとセッターメソッド

class Person
  attr_accessor :name
end

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

あなたがクラスPersonを持っているとしましょう。

class Person
end

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

明らかにメソッドnameは決して定義しませんでした。 それをしましょう。

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

ああ、名前を読むことはできますが、名前を付けることはできません。 それらは2つの異なる方法です。 前者は読者と呼ばれ、後者はライターと呼ばれます。 私たちはまだ作家を作っていませんでしたので、それをやりましょう。

class Person
  def name
    @name
  end

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

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

驚くばかり。 これで、リーダとライターのメソッドを使って@nameインスタンス変数を作成し読み込むことができます。 ただし、これは頻繁に行われますが、毎回これらのメソッドを書くのに時間を費やすのはなぜですか? 私たちはそれをより簡単に行うことができます。

class Person
  attr_reader :name
  attr_writer :name
end

これも繰り返し得ることができます。 あなたはリーダーとライターの両方がアクセサーを使いたいときに!

class Person
  attr_accessor :name
end

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

同じように動作します! そして、私たちの人物オブジェクトのインスタンス変数@nameは、手動で行ったときと同じように設定されるので、他のメソッドでも使用できます。

class Person
  attr_accessor :name

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

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

それでおしまい。 attr_readerattr_writer 、およびattr_accessorメソッドが実際にあなたのためにメソッドを生成する方法を理解するために、他の答え、本、ルビドキュメントを読んでください。


このモジュールの名前付き属性を定義します。名前はsymbol.id2nameで、インスタンス変数(@name)とこれに対応するアクセスメソッドを作成して読み取ります。 また、name =と呼ばれるメソッドを作成して属性を設定します。

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

これは、インスタンス変数のgetterメソッドとsetterメソッドを定義する単なるメソッドです。 実装例は次のとおりです。

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

上記の回答のほとんどはコードを使用しています。 この説明は、コードを使用せずにそれに答えようとしています:

類推による説明

社外の当事者は内部のCIAの秘密にアクセスできない

  • 本当に秘密の場所を想像しよう:CIA。 CIA内の人々とは別に、CIAで何が起こっているかは誰も知りません。 つまり、外部の人々はCIAの情報にアクセスすることはできません。 しかし、組織が完全に秘密であることはうまくないので、特定の情報が外部に公開されています - CIAが誰にでも当然知りたいと思うものだけです:例えば、CIAのディレクター、その他の情報:例えば、イラクやアフガニスタンの秘密諜報員は誰であろうか。この種のものは今後150年間は秘密になるだろう。

  • あなたがCIA外にいる場合は、公開されている情報のみにアクセスできます。 または、CIA用語を使用するには、「消去された」情報にしかアクセスできません。

  • CIAがCIA外の一般市民に利用可能にしたい情報は、 属性と呼ばれます。

読み書き属性の意味:

  • CIAの場合、ほとんどの属性は「読み取り専用」です。 これは、あなたがCIAのにある党であるならば、「CIAの責任者は誰ですか?」と尋ねることができます。 あなたはまっすぐな答えを得るでしょう。 しかし、「読み取り専用」属性ではできないことは、CIAの変更を変更することです。 あなたは電話をかけることができず、突然Kim Kardashianを監督にしたい、あるいはParis HiltonをCommander in Chiefにしたいと決めています。

  • 属性があなたに「書き込み」アクセスを与えた場合、あなたが外にいても、あなたは望むならば変更することができます。 さもなければ、あなたができる唯一のことは読むことです。

    言い換えれば、アクセサーは、アクセサーが読み取りアクセッサであるか書き込みアクセッサであるかに応じて、外部の人がアクセスできない組織に対して、問い合わせを行い、変更を加えることができます。

クラス内のオブジェクトは簡単に互いにアクセスできます

  • 一方、既にCIAの中にいたら、カブールのCIA職員を簡単に呼び出せて、カブールの情報提供者と仕事をしてビールを飲みたいかどうか聞いてみることができます。 しかし、あなたがCIAの外にいれば、あなたはアクセス権が与えられません。あなたは彼らが誰であるかを知ることができず、自分の任務を変更することはできません(書き込みアクセス)。

クラスとその中の変数、プロパティ、メソッドにアクセスするあなたの能力と全く同じこと。 HTH! 何か質問がありましたら、私に尋ねてください。


単にattr-accessorは、指定された属性のsetterメソッドとsetterメソッドを作成します


私は、自分自身のような新しいRuby /プログラマを混乱させるものの一部は次のようだと思う:

「なぜインスタンスに特定の属性(名前など)があり、その属性にすべての値を指定できるのはなぜですか?

もう少し一般化されましたが、これは私がクリックした方法です:

与えられた:

class Person
end

私たちはPersonをそのような事柄に関して名前や他の属性を持つことのできるものと定義していません。

だから私たちは:

baby = Person.new

...名前を付けようとする...

baby.name = "Ruth"

Rubylandでは、オブジェクトのPersonクラスが「名前」と関連付けられているか、それを持つことができるものではないため、 エラーが発生します ...まだ!

しかし、Personクラス( baby )のインスタンスには 'name'という属性が追加できるように、指定されたメソッド(以前の回答を参照)を使用することができます。したがって、構文クラスを取得するだけでなくその名前を設定するが、そうすることは意味がある」と語った。

もう一度、この質問をやや異なった、より一般的な角度から叩いてください。しかし、これは、このスレッドに向かうPersonクラスの次のインスタンスに役立ちます。


私もこの問題に直面し、この質問にやや長い答えを書きました。 これにはいくつかの素晴らしい答えがありますが、より明確なものを探している人は、私の答えが助けてくれることを願っています

メソッドの初期化

初期化を使用すると、クラスの新しいインスタンスを作成するたびに、コードの別の行に設定するのではなく、インスタンスの作成時にオブジェクトのインスタンスにデータを設定できます。

class Person
  attr_accessor :name

  def initialize(name)
    @name = name
  end


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

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

上記のコードでは、DennisをInitializeのパラメータに渡してinitializeメソッドを使用して、「Denis」という名前を設定しています。 initializeメソッドを使わずに名前を設定したければ、次のようにすることができます:

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

上記のコードでは、オブジェクトの初期化時に値を設定するのではなく、person.nameを使用してattr_accessor setterメソッドを呼び出して名前を設定します。

この作業を行う「方法」はどちらも、初期化は時間とコードの節約になります。

これは初期化の唯一の仕事です。 メソッドとしてinitializeを呼び出すことはできません。 実際にインスタンスオブジェクトの値を取得するには、ゲッターとセッター(attr_reader(get)、attr_writer(set)、attr_accessor(both))を使用する必要があります。 これらの詳細については、以下を参照してください。

ゲッター、セッター(attr_reader、attr_writer、attr_accessor)

Getters、attr_reader:ゲッターの目的は、特定のインスタンス変数の値を返すことです。 これについては、以下のサンプルコードを参照してください。

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

上記のコードでは、Item "example"のインスタンスでメソッド "item_name"と "quantity"を呼び出しています。 "puts example.item_name"と "example.quantity"は、 "example"に渡されたパラメータの値を返す(または "取得")し、それらを画面に表示します。

幸いなことに、Rubyには、このコードをより簡潔に書くための固有のメソッドがあります。 attr_readerメソッド。 以下のコードを参照してください。

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

この構文はまったく同じように機能し、6行のコードを保存するだけです。 あなたがItemクラスに起因する州を5つ増やしたとしたら? コードはすばやく長くなるでしょう。

Setters、attr_writer:私が最初にsetterメソッドを使用したことは、私の目ではinitializeメソッドと同じ機能を実行しているようでした。 以下では私の理解に基づいてその違いを説明します。

前述のように、initializeメソッドでは、オブジェクトの作成時にオブジェクトのインスタンスの値を設定できます。

しかし、後で、インスタンスの作成後に値を設定したい場合や、初期化後に値を変更したい場合はどうすればよいでしょうか? これは、セッターメソッドを使用するシナリオです。 それは違いです。 最初にattr_writerメソッドを使用しているときに、特定の状態を「設定」する必要はありません。

以下のコードは、Setterメソッドを使用してItemクラスのこのインスタンスのitem_name値を宣言する例です。 独自のコードをテストしたい場合に備えて、getterメソッドattr_readerを引き続き使用して、値を取得して画面に出力できることに注意してください。

class Item

attr_reader :item_name

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

end

以下のコードは、attr_writerを使用してコードを短くして私たちの時間を節約する例です。

class Item

attr_reader :item_name
attr_writer :item_name

end

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

以下のコードは、initializeを使用して作成時にitem_nameのオブジェクト値を設定するところで、上記の初期化の例を繰り返したものです。

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:attr_readerとattr_writerの両方の機能を実行し、さらに1行のコードを保存します。







ruby