2017-09-26 5 views
0

私はサブクラス化のために構築されたクラスを持っています。Rubyで以前に与えられたブロックを実行するメソッドを作成するには?

class A 
    def initialize(name) 
    end 

    def some 
    # to define in subclass 
    end 
end 

# usage 
p A.new('foo').some 
#=> nil 

私の場合、インスタンスが1つだけ必要なので、サブクラスを作成したくありません。したがって、次の使用方法をサポートするようにinitializeメソッドを変更します。

p A.new('foo') { 'YEAH' }.some 
#=> YEAH 

上記の使用方法をどのようにサポートできますか?


私はRuby 1.8.7プロジェクトで以下の解決策を見つけましたが、彼らは私には奇妙に見えます。

class A 
    def singleton_class 
    class << self; self; end 
    end 

    def initialize(name, &block) 
    @name = name 
    self.singleton_class.send(:define_method, :some) { block.call } if block_given? 
    end 

    def some 
    # to define in subclass 
    end 
end 

答えて

3

あなたが上で、後でそれをインスタンス変数にblock argumentを保存し、callすることができます:あなたはまた、ブロックに引数を渡すことができ

class A 
    def initialize(name, &block) 
    @name = name 
    @block = block 
    end 

    def some 
    @block.call 
    end 
end 

A.new('foo') { 'YEAH' }.some 
#=> "YEAH" 

class A 
    # ... 
    def some 
    @block.call(@name) 
    end 
end 

A.new('foo') { |s| s.upcase }.some 
#=> "FOO" 

それともinstance_execブロックで受信者のコンテキスト:

class A 
    # ... 

    def some 
    instance_exec(&@block) 
    end 
end 

カプセル化をバイパスできます。

A.new('foo') { @name.upcase }.some 
#=> "FOO" 
関連する問題