私は理解しにくい時間が午前attr_accessor
中にルビーを。
誰かがこれを私に説明できますか?
私は理解しにくい時間が午前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つの異なる方法です。前者はリーダーと呼ばれ、後者はライターと呼ばれます。まだライターを作成していないので、作ってみましょう。
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
を考えます。personオブジェクトのインスタンス変数は、手動で設定した場合と同じように設定されるため、他のメソッドで使用できます。
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
は、それが現在のクラスで呼び出されるメソッドであり、:name
そのメソッドに渡すパラメーターであることを理解する必要があります。これは特別な構文ではなく、単純なメソッド呼び出しです。@name
変数を指定する場合、@ nameにはが含まれるため、意味がありませんnil
。だから、書くようなものattr_accessor nil
です。作成する必要がある変数を渡さず、変数を呼び出す名前を渡します。
name
と変数@name
は同じものではありません。それらを混同しないでください。@name
クラスにインスタンス変数があり、attr_reader :name
それを外部から読み取れるように定義します。なしattr_reader
あなたがアクセスできる簡単な方法はありません@name
、あなたのクラスの外には。
attr_accessorは単なるメソッドです。(リンクはそれがどのように機能するかについてより多くの洞察を提供するはずです-生成されたメソッドのペアを見てください、そしてチュートリアルはそれを使用する方法をあなたに示すはずです。)
コツは、Rubyでの定義でclass
はなく(C ++やJavaなどの言語では「単なる定義」です)、評価される式です。attr_accessor
現在のクラスを変更するメソッドが呼び出されるのは、この評価中です-暗黙のレシーバーを覚えておいてくださいself.attr_accessor
。self
この時点で「オープン」クラスのオブジェクトです。
attr_accessor
と友人の必要性は、まあ、です:
Smalltalkと同様に、Rubyでは、そのオブジェクトのメソッド1の外部でインスタンス変数にアクセスできません。つまり、インスタンス変数x.y
には、JavaやPythonのように一般的な形式ではアクセスできません。Ruby y
では常に送信するメッセージ(または「呼び出す方法」)として解釈されます。したがって、attr_*
メソッドは、@variable
動的に作成されたメソッドを介してインスタンスアクセスをプロキシするラッパーを作成します。
ボイラープレートは吸う
これで細かい詳細の一部が明確になることを願っています。ハッピーコーディング。
1これは厳密には当てはまりません。また、この周りにいくつかの「テクニック」がありますが、「パブリックインスタンス変数」アクセスの構文サポートはありません。
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
ようやくここに見つかりました!私の問題は解決しましたが、このような実装例がどこにあるのか知りたいのですが(book / official doc)?
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の外部の一般の人々に提供したい情報は、属性と呼ばれます。
読み取りおよび書き込み属性の意味:
CIAの場合、ほとんどの属性は「読み取り専用」です。これは、CIAの外部のパーティーの場合、「CIAのディレクターは誰ですか?」と尋ねることができることを意味します。正解が得られます。しかし、「読み取り専用」属性ではできないのは、CIAに変更を加えることです。たとえば、電話をかけることができず、キムカーダシアンをディレクターにしたい、またはパリスヒルトンを最高司令官にしたいと突然決めたとします。
属性によって「書き込み」アクセス権が付与されている場合は、外にいても必要に応じて変更を加えることができます。そうでなければ、あなたができる唯一のことは読むことです。
言い換えると、アクセサは、アクセサが読み取りアクセサであるか書き込みアクセサであるかに応じて、外部の人を許可しない組織に問い合わせを行ったり、変更を加えたりすることができます。
クラス内のオブジェクトは互いに簡単にアクセスできます
クラスについてもまったく同じであり、クラス内の変数、プロパティ、メソッドにアクセスする機能も備えています。HTH!ご不明な点がございましたら、お気軽にお問い合わせください。
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"
私もこの問題に直面し、この質問に対してやや長い回答を書きました。これにはすでにいくつかの素晴らしい答えがありますが、より明確にすることを探している人は誰でも、私の答えが役に立てば幸いです
メソッドの初期化
Initializeを使用すると、クラスの新しいインスタンスを作成するたびにコード内の別の行にデータを設定する必要がなく、インスタンスの作成時にオブジェクトのインスタンスにデータを設定できます。
class Person
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セッターメソッドを呼び出すことで名前を設定しています。
この作業を行う両方の「方法」ですが、初期化により時間とコードの行を節約できます。
これが初期化の唯一の仕事です。メソッドとして初期化を呼び出すことはできません。インスタンスオブジェクトの値を実際に取得するには、ゲッターとセッター(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」に渡されたパラメーターの値を返し(または「get」)、それらを画面に表示します。
幸いにも、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メソッドと同じ機能を実行しているように見えたということです。以下、私の理解に基づいて違いを説明します。
前述のように、initializeメソッドを使用すると、オブジェクトの作成時にオブジェクトのインスタンスの値を設定できます。
しかし、インスタンスの作成後に後で値を設定する場合、または初期化後に値を変更する場合はどうでしょうか。これは、setterメソッドを使用するシナリオです。それが違いです。最初にattr_writerメソッドを使用しているときに、特定の状態を「設定」する必要はありません。
以下のコードは、setterメソッドを使用して、Itemクラスのこのインスタンスの値item_nameを宣言する例です。自分でコードをテストする場合に備えて、値を取得して画面に出力できるように、引き続きゲッターメソッド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のオブジェクト値を設定するために初期化を使用している上記の初期化の例の繰り返しです。
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 /プログラマー(私のように)を混乱させるものの一部は次のとおりです:
「インスタンスに特定の属性(名前など)があることを伝えて、その属性に値をすべて一度に与えることができないのはなぜですか?」
もう少し一般化されていますが、これが私にとってクリックした方法です:
与えられた:
class Person
end
Person を名前を持つことができるものとして定義していませんやその他の属性を。
したがって、次の場合:
baby = Person.new
...そして、名前を付けようとします...
baby.name = "Ruth"
私たちは、取得エラー Rubylandで、対象のPersonクラスが関連付けられてか、「名前」を有することのできるものではありません、ので...まだ!
しかし、「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
。
例:
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
and はありませんdef balance
。その場合は、以下の2つのコマンドを使用できます。しかし、これらの2つの方法はありません。しかし、あなたがすることができますアクセスし、あなたがしたいかのように属性をアクセスを経由する方法をattr_accessor
!したがって、単語attr_accessor
。属性。アクセサ。メソッドにアクセスするのと同じように属性にアクセスします。
追加attr_accessor :balance, :owner
するbalance
と、owner
「メソッド」を読み書きできます。これで、最後の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
私はルビーは初めてで、次の奇妙さを理解するだけで対処する必要がありました。将来、誰かを助けるかもしれません。最後に、上記のとおり、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クラスのインスタンス(オブジェクト)です。オブジェクトの外部からwheelインスタンス変数の値を読み取ろうとして失敗しました。Rubyがcオブジェクト内でwheelという名前のメソッドを呼び出そうとしましたが、そのようなメソッドが定義されていませんでした。つまり、object_name.attribute_nameは、オブジェクト内のattribute_nameという名前のメソッドを呼び出そうとします。外部からwheel変数の値にアクセスするには、その名前でインスタンスメソッドを実装する必要があります。これにより、呼び出されたときにその変数の値が返されます。これは、アクセサメソッドと呼ばれます。一般的なプログラミングコンテキストでは、オブジェクトの外部からインスタンス変数にアクセスする通常の方法は、ゲッターメソッドおよびセッターメソッドとも呼ばれるアクセサーメソッドを実装することです。
次の例では、オブジェクトの外部からwheel変数にアクセスするために、ゲッターメソッドとセッターメソッドをCarクラスに追加しています。これは、ゲッターとセッターを定義する「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
上記の例は機能し、同様のコードが他の言語でゲッターおよびセッターメソッドを作成するために一般的に使用されます。ただし、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組み込みメソッドを使用して、オブジェクトの外部からインスタンス変数にアクセス(読み取りおよび書き込み)することができます。ただし、カプセル化をバイパスするとあらゆる種類の混乱を招く傾向があるため、これはめったに正当化できず、通常は悪い考えです。
うーん。良い答えがたくさん。ここに私の数セントです。
attr_accessor
繰り返しの方法をクリーンアップ(乾燥)するのに役立つ簡単な方法です。getter and setter
そのため、セッターやゲッターについて心配することなく、ビジネスロジックの記述にさらに集中できます。
他のファイルに対するattr_accessorの主な機能は、他のファイルのデータにアクセスする機能です。
したがって、通常はattr_readerまたはattr_writerがありますが、良いニュースは、Rubyではこれら2つをattr_accessorと組み合わせることができるということです。丸みを帯びているか、用途が広いので、これを自分の行く方法と考えています。また、Railsではバックエンドで実行するため、これが排除されていることを覚えておいてください。つまり、言い換えると、特定のことを心配する必要がないので、他の2つよりもattr_acessorを使用する方がベターです。アクセサがすべてをカバーします。これはより一般的な説明ですが、初心者には役立ちました。
これが役に立てば幸い!