Rubyには、次のようなキーを使用してインスタンス変数を共有するための便利で便利な方法があります。
attr_accessor :var
attr_reader :var
attr_writer :var
なぜ私が選ぶのでしょうかattr_reader
、それともattr_writer
単に使用できるのattr_accessor
でしょうか?パフォーマンスのようなものはありますか(私は疑っています)?理由があると思います。そうでなければ、そのようなキーを作成しなかったでしょう。
Rubyには、次のようなキーを使用してインスタンス変数を共有するための便利で便利な方法があります。
attr_accessor :var
attr_reader :var
attr_writer :var
なぜ私が選ぶのでしょうかattr_reader
、それともattr_writer
単に使用できるのattr_accessor
でしょうか?パフォーマンスのようなものはありますか(私は疑っています)?理由があると思います。そうでなければ、そのようなキーを作成しなかったでしょう。
さまざまなアクセサーを使用して、コードを読んでいる誰かに意図を伝え、パブリックAPIがどのように呼び出されても正しく機能するクラスを簡単に記述できるようにすることができます。
class Person
attr_accessor :age
...
end
ここでは、年齢の読み取りと書き込みの両方が可能であることがわかります。
class Person
attr_reader :age
...
end
ここでは、年齢しか読めないことがわかります。このクラスのコンストラクターによって設定され、その後は一定のままであると想像してください。年齢のミューテーター(ライター)があり、年齢が設定されると変更されないと仮定してクラスが作成された場合、そのミューテーターを呼び出すコードが原因でバグが発生する可能性があります。
しかし、舞台裏で何が起こっているのでしょうか?
あなたが書く場合:
attr_writer :age
それは次のように翻訳されます:
def age=(value)
@age = value
end
あなたが書く場合:
attr_reader :age
それは次のように翻訳されます:
def age
@age
end
あなたが書く場合:
attr_accessor :age
それは次のように翻訳されます:
def age=(value)
@age = value
end
def age
@age
end
それを知って、それについて考える別の方法があります:attr _...ヘルパーがなく、アクセサを自分で作成する必要がある場合、クラスに必要な数よりも多くのアクセサを作成しますか?たとえば、年齢を読み取るだけでよい場合、それを書き込むことができるメソッドも記述しますか?
アクセサは変数へのアクセスを制限しますが、その内容は制限しないことを理解することが重要です。ルビーでは、他のいくつかのオブジェクト指向言語と同様に、すべての変数はインスタンスへのポインターです。したがって、たとえばハッシュの属性があり、それを「読み取り専用」に設定した場合、常にそのコンテンツを変更できますが、ポインタのコンテンツは変更できません。これを見てください:
> class A
> attr_reader :a
> def initialize
> @a = {a:1, b:2}
> end
> end
=> :initialize
> a = A.new
=> #<A:0x007ffc5a10fe88 @a={:a=>1, :b=>2}>
> a.a
=> {:a=>1, :b=>2}
> a.a.delete(:b)
=> 2
> a.a
=> {:a=>1}
> a.a = {}
NoMethodError: undefined method `a=' for #<A:0x007ffc5a10fe88 @a={:a=>1}>
from (irb):34
from /usr/local/bin/irb:11:in `<main>'
ご覧のとおり、ハッシュ@aからキーと値のペアを削除し、新しいキーを追加したり、値を変更したりすることができます。ただし、は読み取り専用のインスタンス変数であるため、新しいオブジェクトを指すことはできません。
オブジェクトのすべての属性がクラスの外部から直接設定されることを意図しているわけではありません。すべてのインスタンス変数にライターがあるということは、一般に、カプセル化が弱いことの兆候であり、クラス間に過度の結合を導入していることを警告しています。
実用的な例として:私はあなたがコンテナの中にアイテムを入れるデザインプログラムを書きました。アイテムは持っていましたattr_reader :container
が、ライターを提供することは意味がありませんでした。アイテムのコンテナを変更する必要があるのは、新しいコンテナに配置するときだけであり、これには位置情報も必要です。
クラスの外部からインスタンス変数に完全にアクセスできるようにする必要はありません。インスタンス変数への読み取りアクセスを許可することは理にかなっているが、それに書き込むことは理にかなっていない場合がたくさんあります(たとえば、読み取り専用ソースからデータを取得するモデル)。逆の場合もありますが、頭のてっぺんから工夫されていないものは思い浮かびません。