2011-11-03 10 views
5

の文字列変数を変更することを許可します。何か奇妙な動作に陥り、他の誰かが私が見ているものを確認できるかどうか疑問に思う。Rubyのattr_readerは、<<

メンバー変数を持つクラスを作成し、attr_readerを使用してそのクラスを読み取ることができるとします。私は次のことを行うときに

class TestClass 
    attr_reader :val 

    def initialize(value) 
    @val = value 
    end 
end 

は今、私が唯一それが読み取り権限を付与しているにもかかわらず、@valの値を変更しているようです。

test = TestClass.new('hello') 
puts test.val 
test.val << ' world' 
puts test.val 

これは

hello 
hello world 

を返すこれはIRBで私がやったいくつかのテスト、これは常にあなたが本当にvalの属性を書いていない場合

+0

'attr_reader'は値を設定できない、つまり' value = 'メソッドが定義されていないことを意味します。確かに、あなたがオブジェクトのメソッドを調整できないということを意味するわけではありません –

答えて

4

であればそれほどわからないからだけの結果です。あなたはそれを読んでそれに関するメソッドを呼び出しています( '< <'メソッド)。

あなたが記述する変更の種類を妨げるアクセサを使用する場合は、attr_readerを使用する代わりに@valのコピーを返すメソッドを実装すると便利です。あなたの例の

2

ほんの少しの修正:

test = TestClass.new([]) 

今あなたが得る(内部ビューを取得するためのpとプットを交換する)必要があります。

[] 
['hello'] 

それは同じことです。あなたは 'val'を読んで、今それで何かをすることができます。私の例では、Arrayに何かを追加します。あなたの例では、Stringに何かを追加します。

読み取りアクセスはオブジェクト(変更可能)を読み取り、書き込みアクセスは属性を変更します(置き換えられます)。

はおそらく、あなたはfreezeを探します。このが予期しないが、これはまさに正しいと思えますが

__temp.rb:12:in `<main>': can't modify frozen string (RuntimeError) 
hello 
0

:これはで終わる

class TestClass 
    attr_reader :val 

    def initialize(value) 
    @val = value 
    @val.freeze 
    end 
end 

test = TestClass.new('hello') 
puts test.val 
test.val << ' world' 
puts test.val 

。私に説明させてください。

attr_readerおよびattr_writerクラスマクロメソッドは、インスタンス変数に「getter」メソッドと「setter」メソッドを定義します。

「ゲッター」メソッドを使用しないと、オブジェクトのコンテキストにアクセスしていないため、オブジェクトのインスタンス変数にアクセスできません。 「セッター」メソッドは、基本的にこれです:メソッド自体のセットで変更可能なオブジェクトをインスタンス変数ポイントので

def variable=(value) 
    @variable = value 
end 

あなたはそれを「取得」し、それを操作する場合、それはこれらの変更がすることを理にかなって取る。上記のセッターメソッドを使用してvariable.<<(value)を呼び出す必要はありません。

2

割り当ては、変更とは異なり、変数はオブジェクトとは異なります。

test.val << " world" 

が参照オブジェクト変形であろう一方、

test.val = "hello world" 

は、(動作しない)可変@valインスタンスへ割り当ての場合でありますby @val

Why does the absence of the assignment operator permit me to modify a Ruby constant with no compiler warning?も同様の質問ですが、インスタンス変数ではなく定数について説明しています。

関連する問題