2010-05-03 59 views
2
def singleton_class 
     class << self 
     self 
     end 
    end 

    class Human 
     proc = lambda { puts 'proc says my class is ' + self.name.to_s } 

     singleton_class.instance_eval do 
     define_method(:lab) do 
      proc.call 
     end 
     end 
    end 

    class Developer < Human 
    end 

    Human.lab # class is Human 
    Developer.lab # class is Human ; oops 

以下解決方案的工作。Instance_eval:爲什麼子類的類是超類

def singleton_class 
    class << self 
    self 
    end 
end 

class Human 
    proc = lambda { puts 'proc says my class is ' + self.name.to_s } 
    singleton_class.instance_eval do 
    define_method(:lab) do 
     self.instance_eval &proc 
    end 
    end 
end 

class Developer < Human 
end 

Human.lab # class is Human 
Developer.lab # class is Human ; oops 

爲什麼Developer.lab報告它是Human?當調用Developer.lab時,可以做些什麼以便proc報告開發人員。

回答

4

這很微妙,但歸結爲簡單地調用塊(在這種情況下它作爲一個正常閉合,並self對應於它被定義在哪裏,即,在Human),或使用它(直接地)用作一個方法定義或instance_eval塊:

def singleton_class 
    class << self 
    self 
    end 
end 


class Human 

    PROC = proc { puts 'proc says my class is ' + self.name.to_s } 

    singleton_class.instance_eval do 
    define_method(:lab) do 
     PROC.call 
    end 
    define_method(:lab2, &PROC.method(:call)) 

    define_method(:lab3) do 
     instance_eval(&PROC) 
    end 
    define_method(:lab4, &PROC) 
    end 
end 

class Developer < Human 
end 

Human::PROC.call # => "class is Human" (original closure) 
Developer.lab  # Same as previous line, so "class is Human" (original closure) 
Developer.lab2 # ditto 

Developer.instance_eval(&Human::PROC) # => "class is Developer" (instance_eval changes sets a different scope) 
Developer.lab3 # Same as previous line, so "class is Developer" 
Developer.lab4 # ditto 
1

我得想想究竟爲什麼這個作品一點點,但目前它確實工作:

class Human 
    proc = -> { name } 

    define_singleton_method(:lab, &proc) 
end 

class Developer < Human; end 

require 'test/unit' 
class TestClosures < Test::Unit::TestCase 
    def test_that_the_human_class_is_named_human 
    assert_equal 'Human', Human.lab 
    end 
    def test_that_the_developer_class_is_named_developer 
    assert_equal 'Developer', Developer.lab 
    end 
end 
+0

它的工作。不知道爲什麼。謝謝。 – 2010-05-03 14:46:44

+0

希望我的回答能夠揭示_why_ – 2010-05-03 16:12:19

4

的封閉是捕獲的背景下,它被定義 - 就像關閉應該做的一樣。所以,當它被調用時,它將使用它捕獲的上下文的引用。閉包不是定義預期功能的理想工具。而不是proc.call,「define_method」調用的內容應該是「puts」proc說我的類是'+ name.to_s「