2010-12-08 17 views
6

メソッドを持つクラスとそのメソッドがないクラスを定義しようとしていて、後者のクラスのオブジェクトがそのメソッドのインスタンスを元のクラスのインスタンスから '学習'することを許可しています。異なるRubyクラス間でシングルトンメソッドをコピーするにはどうすればよいですか?

これは私の試みです(Ruby 1.9.2) - ラムダバインディングで 'self'の値を変更しようとすると、(行コメントで "BREAKS!"

これを解決する方法を考えることができれば、私は見つけ出すことに魅了されます。

class Skill 

    attr_accessor :name 
    attr_accessor :technique 

    def initialize(name, &technique_proc) 
    @name = name 
    @technique = lambda(&proc) 
    end 

end 

class Person 

    attr_accessor :name 

    def initialize(name) 
    @name = name 
    end 

    def method_missing(m, *args) 
    "#{@name} the #{self.class}: I don't know how to #{m}" 
    end 

    def learn_skill(skill) 
    puts "#{@name} the #{self.class} is learning skill: #{skill.name}" 
    actual_self = self 
    eval "self = #{actual_self}", skill.technique.binding ####### BREAKS! 
    define_singleton_method skill.name.to_sym, skill.technique 
    end 

    def teach_skill(skill_name) 
    skill = nil 
    if self.respond_to?(skill_name) 
     puts "#{@name} the #{self.class} is teaching skill: #{skill_name}" 
     skill_method = self.method(skill_name.to_sym) 
     skill_proc = skill_method.to_proc 
     skill_lambda = lambda(&skill_proc) 
     skill = Skill.new(skill_name, &skill_lambda) 
    end 
    skill 
    end 

end 

class Teacher < Person 

    def speak(sentence) 
    "#{@name} the #{self.class} is now saying \"#{sentence}\"!" 
    end 

    def jump(number_of_feet) 
    "#{name} the #{self.class} is now jumping #{number_of_feet} high!" 
    end 

end 

miss_mollyflop = Teacher.new("Miss Mollyflop") 
little_billey = Person.new("Little Billy") 

puts miss_mollyflop.speak("Good morning, children!") 
puts little_billey.speak("Good morning, Miss Mollyflop!") 

speak_skill = miss_mollyflop.teach_skill("speak") 
little_billey.learn_skill(speak_skill) 

puts little_billey.speak("Good morning, Miss Mollyflop!") 

これの出力は次のようになります。

Miss Mollyflop the Teacher is now saying "Good morning, children!"! 
Little Billy the Person: I don't know how to speak 
Miss Mollyflop the Teacher is teaching skill: speak 
Little Billy the Person is learning skill: speak 
test.rb:27:in `eval': (eval):1: Can't change the value of self (SyntaxError) 
self = #<Person:0x1482270> 
    ^
(eval):1: syntax error, unexpected $end 
self = #<Person:0x1482270> 
         ^
     from test.rb:27:in `learn_skill' 
     from test.rb:64:in `<main>' 
+1

コードを適切にフォーマットすることができますか? – Theo

+1

「自己」を直接変更することはできません。読み取り専用です。 –

+0

コードフォーマットを修正しました(無料)。次回は、コードまたは出力を強調表示してから、「101010」ボタンをクリックしてコードとしてフォーマットします。 –

答えて

0

使用Object2module:gem install object2module

require 'object2module' 

o = Object.new 
def o.speak 
    puts "hello from o" 
end 

m = Object.new 
m.gen_extend o 

m.speak #=> "hello from o" 
+0

私はObject2モジュールをチェックアウトしました。私はソースを勉強するのを楽しみます。 Rubyは絶えずより多くの層の魅力を提供しているようです。ドキュメントから、別のクラスのシングルトン、別のシングルトンの特定のメソッドを選択的に「教える」ことができるかどうかはわかりませんでした。そうでない場合は、コードを調整する方法について考えていますか?お返事ありがとうございました.BTW: – Anthony

+0

ソースはこちらです:https://github.com/banister/object2module – horseyguy

0

あなたはそれが可能だ別のクラスからメソッド間でコピーしたい場合は、しかし、もし方法状態を変更すると、メソッドが後でバインドされるオブジェクト上にない元のオブジェクトの状態が変更されます(これは、メソッドがmのProcラッパーの代わりに実際にはコピーされないためです)。新しいオブジェクトにメソッドとしてバインドされています)。

a = Object.new 
def a.hello 
    puts "hello world from a" 
end 

b = Object.new 
b.define_singleton_method(:hello, &a.method(:hello)) 
b.hello #=> "hello world from a" 
関連する問題