2012-03-17 1 views
1

私は、initializeメソッドのインスタンス変数の値を設定しながら、attr_readerメソッドを作成する方法を探していますか?たとえば、次のコード:initializeメソッド内の対応するインスタンス変数の値を設定しながら、attr_readerメソッドを作成しますか?

class SomeClass 
    attr_reader :hello 
    def initialize(arg) 
    @hello = arg 
    end 
end 

私は次のように書くための方法を探しています:

class SomeClass 
    def initialize(arg) 
    some_method_as_described_in_question(@hello, arg) 
    end 
end 

は、私が説明している何をして方法はRubyのビルトインクラスとモジュールに存在していますか?

+0

いいえ、このような方法はありません。 –

+0

これは非常に便利なもののようですが、アクセス制御の問題ですか?なぜそれが含まれていないのですか? – rudolph9

+1

インスタンスメソッド( 'initialize')で呼び出すメソッドを含めて、クラスのもの、つまり他のインスタンスのものを変更するのはおそらく変です。それとも、現在のインスタンスにリーダーを設定したいだけですか? Ruby 1.9で 'define_singleton_method'を使ってこれを行うことができます:https://gist.github.com/be3485dde76c0da72a00おそらくあなたはその質問を明確にすることができますか? –

答えて

4

あなたは、メソッド内からeigenclassを開いて、そこに属性を設定することができます

class SomeClass 
    def initialize(arg) 
    (class << self; self; end).send(:attr_reader, :hello) 
    @hello = arg 
    end 
end 

そのように各インスタンスのeigenclassは、その属性リーダーを持っています。しかし、実際には、属性名が動的であり、インスタンスごとに異なる場合にのみ、そのようにすることが理にかなっています。それが常にhelloの場合、元のコードブロックのようにクラス内で定義するだけの欠点はありません。あなたが動的属性名に渡している場合

たとえば、あなたはこのようにそれを行うことができます:

class SomeClass 
    def initialize(attr, arg) 
    (class << self; self; end).send(:attr_reader, attr.to_sym) 
    instance_variable_set("@#{attr}", arg) 
    end 
end 

これはRubyの1.8と互換性があります。初期化子とアクセサメソッドを取得するために、私は質問を理解している場合

class SomeClass 
    def initialize(attr, arg) 
    define_singleton_method(attr) { instance_variable_get("@#{attr}") } 
    instance_variable_set("@#{attr}", arg) 
    end 
end 
+0

非常に良い!自分自身の理解のために、これが正しいかどうかを確認します: 'class << self'はある意味で、それ自身のクラスの追加の定義を作成し、それ自身の定義オブジェクトであるオブジェクトを返し、' send (:attr_reader、:hello) 'は' attr_reader'を作成しますか? – rudolph9

+0

@KurtRudolph、そうですね。すべてのオブジェクトインスタンスが独自のクラスを持っていることを理解してください。クラスの他のインスタンスではなく、そのインスタンスにのみ*影響を与えるメソッドを置くことができます。そして "class << self"はeigenclassをどのようにオープンするかです(あなたが言ったように、自身への参照を返し、sendを使用して目的の属性リーダーを作成します)。 –

+1

@ KurtRudolph、私はあなたの編集を私の答えにundidしました。あなたの編集はもっと単純ではなく、*別のものでした。あなたがリンクしているHenrikの要点は、 "hello"が常にargの*初期値を返すようにするので、それは属性リーダーとはまったく異なります。私が持っている方法では、アトリビュートリーダーと同じように動作するので、 '@hello = ...'を設定し、期待される 'obj.hello'属性を得ることができます。 –

0

わからないが、あなたはStructを使用することができます:あなたの質問にコメントして@HenrikNからヒントを取ると、あなたは、Ruby 1.9でdefine_singleton_methodを使用することができます

class SomeClass < Struct.new(:hello) 
end 

x = SomeClass.new("yo") 
puts x.hello # "yo" 
x.hello = "what up" 
puts x.hello # "what up" 
+0

これは私が探しているものではありません。私は部分的に動的な目的のためにそれがほしいと思うので、部分的にそれを必要としているのは、インスタンス変数を伴うメソッドがそれにアクセスできるメソッド、つまり 'p = SomeClass 。新世界'; puts p.hello 'は、 'attr_reader:hello'と' @hello = arg'を別々に記述することなく、文字列 'world'を出力します。 – rudolph9

0
require 'ostruct' 

p = OpenStruct.new 
p.hello = 'world' 
p.could_be_anything = 'nothing' 
puts p.hello #=> 'world' 
puts p.could_be_anything #=> 'nothing' 
関連する問題