[英]Instance_eval: why the class of subclass is superclass
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
以下解決方案有效
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? 還有什么可以讓proc在調用Developer.lab時報告Developer。
閉包是在定義它的上下文中捕獲self - 就像閉包應該做的那樣。 因此,當它被調用時,它將使用對它捕獲的上下文的引用。 閉包不是定義預期功能的理想工具。 而不是proc.call,“define_method”調用的內容應該是“puts”,proc表示我的類是'+ name.to_s'
它是微妙的,但它歸結為簡單地調用塊(在這種情況下,它充當正常閉包, 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
我必須仔細考慮一下它為什么會起作用,但目前它確實有效:
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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.