私はRubyのattr_accessor
を理解するのに苦労しています。誰かが私にこれを説明できますか?
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つの異なる方法です。前者は reader と呼ばれ、後者は writer と呼ばれます。作家はまだ作成していないので、それをしましょう。
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"
同じように動作します!そしてどう思いますか:personオブジェクトのインスタンス変数@name
は、手動で行ったときと同じように設定されるので、他のメソッドで使用できます。
class Person
attr_accessor :name
def greeting
"Hello #{@name}"
end
end
person = Person.new
person.name = "Dennis"
person.greeting # => "Hello Dennis"
それでおしまい。 attr_reader
、attr_writer
、およびattr_accessor
メソッドが実際にどのようにメソッドを生成するのかを理解するために、他の回答、書籍、Rubyのドキュメントを読んでください。
attr_accessor は 単なるメソッド です。 (リンクはそれがどのように働くかについてのより多くの洞察を提供するべきです - 生成されたメソッドのペアを見てください、そしてチュートリアルはあなたがそれをどのように使うかを示すべきです。)
トリックは、Rubyではclass
が 定義ではない (C++やJavaなどの言語では「単なる定義」である)ですが、 評価される式 です。この評価中に、attr_accessor
メソッドが呼び出されて現在のクラスが変更されます。暗黙のレシーバself.attr_accessor
を覚えておいてください。ここで、self
は、この時点での "open"クラスオブジェクトです。
attr_accessor
と友達の必要性は、そうです:
Smalltalkのように、Rubyはインスタンス変数にメソッド外からアクセスすることを許可していません。1 そのオブジェクトのために。つまり、インスタンス変数はx.y
形式でアクセスすることはできません。JavaやPythonでさえも一般的です。 Rubyではy
は常に送信するメッセージ(または「呼び出すメソッド」)として扱われます。したがって、attr_*
メソッドは、動的に作成されたメソッドを通じてインスタンス@variable
アクセスを代行するラッパーを作成します。
ボイラープレートは吸う
これが細部のいくつかを明確にすることを願っています。ハッピーコーディング.
1 これは厳密には真実ではなく、 これに関するいくつかの "テクニック" がありますが、 "public instance variable"アクセスに対する構文サポートはありません。
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
attr_accessor
はとても簡単です:
attr_accessor :foo
ショートカットです:
def foo=(val)
@foo = val
end
def foo
@foo
end
それはオブジェクトのためのゲッター/セッターに過ぎません
基本的に、彼らはRubyが持っていない、公にアクセス可能なデータ属性を偽造します。
インスタンス変数の取得メソッドと設定メソッドを定義するメソッドです。実装例は次のようになります。
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の外部の一般の人々が利用できるようにしたい情報は、次のように呼ばれます。attributes。
読み取りおよび書き込み属性の意味:
CIAの場合、ほとんどの属性は「読み取り専用」です。つまり、CIAの関係者がexternalの場合、ask: "CIAのディレクターは誰ですか?"ということです。そして、あなたはまっすぐな答えを得るでしょう。しかし、「読み取り専用」属性でcannotすることは、CIAで変更を加えることです。例えば電話をかけることができず、突然決定キムカーダシアンをディレクターにしたい、またはパリスヒルトンを最高司令官にしたい。
属性が「書き込み」アクセス権を与えた場合、必要に応じて、たとえ外部にいても変更を加えることができます。それ以外の場合、できることは読むことだけです。
つまり、アクセサーを使用すると、アクセサーが読み取りアクセサーであるか書き込みアクセサーであるかに応じて、外部のユーザーを受け入れない組織に照会したり、変更したりできます。
クラス内のオブジェクトは互いに簡単にアクセスできます
クラスや、クラス内の変数、プロパティ、メソッドにアクセスする能力についても、まったく同じことが言えます。 HTH!ご質問は、お尋ねください、私は明確にできることを願っています。
OOPの概念に慣れている場合は、getterメソッドおよびsetterメソッドに精通している必要があります。 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のGetterとSetterメソッド
class Person
attr_accessor :name
end
person = Person.new
person.name = "Eshaan"
person.name # => "Eshaan"
私はこの問題にも直面し、この質問に対してやや長い答えを書いた。これについてはすでにいくつかの素晴らしい答えがありますが、もっと明確にしたいと思っている人は誰でも、私の答えが役立つことを願っています
初期化メソッド
Initializeを使用すると、クラスの新しいインスタンスを作成するたびにコード内の別の行にデータを設定しなくても、インスタンスの作成時にデータをオブジェクトのインスタンスに設定できます。
class Person
attr_accessor :name
def initialize(name)
@name = name
end
def greeting
"Hello #{@name}"
end
end
person = Person.new("Denis")
puts person.greeting
上記のコードでは、InitializeのパラメータにDennisを渡して、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セッターメソッドを呼び出して名前を設定します。
この作業をする「初期化」の両方の「方法」は、時間とコード行を節約します。
これが初期化の唯一の仕事です。メソッドとしてinitializeを呼び出すことはできません。インスタンスオブジェクトの値を実際に取得するには、取得メソッドと設定メソッド(attr_reader(get)、attr_writer(set)、およびattr_accessor(both))を使用する必要があります。それらの詳細については下記を参照してください。
ゲッター、セッター(attr_reader、attr_writer、attr_accessor)
ゲッター、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
上記のコードでは、アイテム「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つあるかどうかを想像してみてください。コードはすぐに長くなります。
セッター、attr_writer:セッターメソッドと最初に私を交差させたのは、私の目では初期化メソッドと同じ機能を実行するように見えたということです。以下に、私の理解に基づいて違いを説明します。
前述のように、initializeメソッドを使用すると、オブジェクトの作成時にオブジェクトのインスタンスに値を設定できます。
しかし、後でインスタンスを作成した後に値を設定したい場合、または初期化した後に値を変更したい場合はどうしますか?これは、設定メソッドを使用するシナリオです。 IS違い。最初にattr_writerメソッドを使用しているときは、特定の状態を「設定」する必要はありません。
以下のコードは、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"
以下のコードは、作成時にitem_nameのオブジェクト値を設定するためにinitializeを使用している上記のinitializeの例を繰り返したものです。
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行のコードを節約します。
私は(私と同じように)新しいRubyists /プログラマーを混乱させるものの一部だと思います:
「インスタンスに特定の属性(名前など)があるだけで、その属性に1つの値をまとめて指定できないのはなぜですか。」
もう少し一般化したものですが、これが私のためにクリックされた方法です:
与えられた:
class Person
end
Person 名前を持つことができるものやその他の属性は定義していません。
だから私たちはその後:
baby = Person.new
…そして彼らに名前をつけよう….
baby.name = "Ruth"
error が出ます、なぜなら、Rubylandでは、Personクラスのobjectは、 "名前"に関連付けられている、またはそれを持つことができるものではないからです...まだ!
しかし、「Personクラスのインスタンス(baby
)できますは 'name'という属性を持っています。その名前を取得および設定するための構文的な方法はありますが、そうすることは意味があります。」
繰り返しますが、この質問をやや異なるより一般的な観点から叩きますが、これが、このスレッドへの道を見いだすPersonクラスの次のインスタンスに役立つことを願っています。
簡単に言うと、クラスのセッターとゲッターを定義します。
ご了承ください
attr_reader :v is equivalant to
def v
@v
end
attr_writer :v is equivalant to
def v=(value)
@v=value
end
そう
attr_accessor :v which means
attr_reader :v; attr_writer :v
クラスの設定メソッドと取得メソッドを定義するのと同じです。
単にattr-accessor
は指定された属性に対してgetter
とsetter
メソッドを作成します
それを理解するもう1つの方法は、attr_accessor
を持つことによってどのエラーコードが排除されるかを把握することです。
例:
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
以下の方法があります。
$ bankie = BankAccout.new("Iggy")
$ bankie
$ bankie.deposit(100)
$ bankie.withdraw(5)
次のメソッドはエラーをスローします。
$ bankie.owner #undefined method `owner'...
$ bankie.balance #undefined method `balance'...
owner
とbalance
は、技術的には メソッド ではなく属性です。 BankAccountクラスにはdef owner
とdef balance
がありません。もしそうなら、あなたは以下の2つのコマンドを使用することができます。しかし、これら2つの方法はありません。しかし、attr_accessor
経由で access メソッドにアクセスするのと同じように、 access attributesにアクセスできます。 それゆえにattr_accessor
という言葉 - 。属性。アクセサメソッドにアクセスするのと同じように属性にアクセスします。
attr_accessor :balance, :owner
を追加すると、balance
とowner
"method"を読み書きできます。今、あなたは最後の2つの方法を使うことができます。
$ bankie.balance
$ bankie.owner
このモジュールの名前付き属性(名前はsymbol.id2name)を定義し、インスタンス変数(@name)とそれを読み取るための対応するアクセス方法を作成します。属性を設定するためのname =というメソッドも作成します。
module Mod
attr_accessor(:one, :two)
end
Mod.instance_methods.sort #=> [:one, :one=, :two, :two=]
属性アクセサ、つまりattr_accessorを要約すると、2つの無料のメソッドが得られます。
Javaのように、それらはゲッターとセッターと呼ばれます。
多くの回答が良い例を示しているので、簡単に説明します。
#the_attribute
そして
#the_attribute =
古いRubyドキュメントではハッシュタグ#はメソッドを意味します。クラス名の接頭辞を含めることもできます。MyClass#my_method
私はRubyが初めてなので、次のような奇妙な点を理解するだけで対処する必要がありました。将来他の誰かを手助けするかもしれません。結局それは上で述べたように、2つの関数(def myvar、def myvar =)は両方とも@myvarにアクセスするために暗黙のうちに取得しますが、これらのメソッドはローカル宣言によってオーバーライドすることができます。
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
属性は、オブジェクトの外部からアクセスできるクラスコンポーネントです。それらは他の多くのプログラミング言語でプロパティとして知られています。それらの値は、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クラスのインスタンス(オブジェクト)です。オブジェクトの外部からwheelsインスタンス変数の値を読み出そうとして失敗しました。起こったのは、Rubyがcオブジェクト内でwheelsという名前のメソッドを呼び出そうとしたが、そのようなメソッドが定義されていなかったことです。つまり、object_name.attribute_nameは、オブジェクト内のattribute_nameという名前のメソッドを呼び出そうとします。外部からwheels変数の値にアクセスするには、その名前でインスタンスメソッドを実装する必要があります。これは呼び出されるとその変数の値を返します。これはアクセサメソッドと呼ばれます。一般的なプログラミングのコンテキストでは、オブジェクトの外部からインスタンス変数にアクセスする通常の方法は、getterメソッドおよびsetterメソッドとも呼ばれるアクセサメソッドを実装することです。ゲッターはクラス内で定義された変数の値を外部から読み取ることを可能にし、セッターはそれを外部から書き込むことを可能にします。
次の例では、オブジェクトの外部からwheels変数にアクセスするために、Carクラスに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組み込みメソッドを使用して、オブジェクトの外部からインスタンス変数にアクセス(読み取りおよび書き込み)することができます。しかしながら、カプセル化を迂回することはあらゆる種類の混乱を招く傾向があるので、これはめったに正当化できず、通常悪い考えです。