编辑:让我稍微谈谈我的意图:
鉴于ruby对象从其类的实例方法获取其方法。
我试图“证明”的是,通过向该对象的类添加实例方法,它们将成为该对象本身的方法。
所以:
class Test;end
Test.class.class_eval do
def foo
puts "I am a method in #{self}"
end
end
Test.foo
=> I am a method in Test
Test.class.foo
=> I am a method in Class
我实际上已经弄明白为什么会这样。那是因为Class.class是...... Class!由于Class将foo作为其实例方法表的一部分,并且由于Class.class指向自身,因此它也将foo作为可调用的实例方法。
为了更多地了解Ruby对象模型,我一直在做一些实验,以下行为让我感到惊讶:
假设我们有一个课程测试:
class Test;end
然后,我们将class_eval Test.class添加到Test对象中:
Test.class.class_eval do
def foo
puts 'foo called!'
end
end
(相当于调用Test.class.send(:define_method,:foo)...)
然后:
irb(main):076:0> Test.foo
=> foo called!
但是将foo发送到课堂也有效:
irb(main):006:0> Test.class.foo
=> foo called!
但是,我仍然无法弄清楚原因。 Class'ingleton_class不包含它(我想到的唯一可能的解释是,该方法被添加到Class的单例类中):
Test.class.singleton_methods
=> [:nesting, :constants]
在这种情况下,方法查找如何工作?为什么发送:foo到Test.class也调用方法?我错过了什么吗?
作为参考,我对Test的实例做了同样的事情:
irb(main):001:0> class Test;end
=> nil
irb(main):002:0> _foo = Test.new
=> #<Test:0x007fa2c39e2f38>
irb(main):003:0> _foo.class.class_eval do
irb(main):004:1* def foo
irb(main):005:2> puts 'foo called!'
irb(main):006:2> end
irb(main):007:1> end
=> :foo
irb(main):008:0> _foo.foo
foo called!
=> nil
irb(main):009:0> _foo.class.foo
NoMethodError: undefined method `foo' for Test:Class
这就像我期望的那样。
提前致谢!
答案 0 :(得分:1)
当您致电Test.class
时,它会返回Test
类不是的实际Test类。
irb(main):001:0> class Test;end
=> nil
irb(main):002:0> Test.class
=> Class
当您致电_foo = Test.new
时,您正在抓取该课程的实例,然后当您致电_foo.class
时,它会返回foo
实例的类Test
< / p>
在您的第一个示例中, 将foo添加到超类,而不是Test
类。
要进一步扩展这一点,您应该做的是在class_eval
类上调用Test
。
最重要的是,你想要的是一个类方法,而不是一个实例方法。因为Test
类实际上是Class
的实例,所以实际上在Class
类中定义了一个实例方法,而不是在Test
中定义类方法。你应该做的是:
Test.class_eval do
def self.foo
puts "foo called!"
end
end
答案 1 :(得分:0)
你把事情搞混了。
Test.class_eval
在Test
的本征类(Test
上执行。)Test.class.class_eval
在Test
的本征类'本征类(显然是Class
)上执行。)Test.class.singleton_methods
返回Class
'本征类的方法。 Test.class.class_eval
实际上会在Class
上执行代码(在您的情况下声明Class
'实例方法。)
Test.foo
被称为w / out问题,因为您已在#foo
上声明Class
而Test
是其实例(以及Test.class
。 )
答案 2 :(得分:0)
长话短说,将foo发送到Test.class的原因是:
Test.class == Class and Class.class == Class
Class.class指向自己。