为什么在类上调用 instance_eval() 时要定义类方法?
Foo = Class.new
Foo.instance_eval do
def instance_bar
"instance_bar"
end
end
puts Foo.instance_bar #=> "instance_bar"
puts Foo.new.instance_bar #=> undefined method ‘instance_bar’
我的理解是,调用 instance_eval<对象上的 /a> 应该允许您为该对象定义实例变量或方法。
但在上面的示例中,当您在类 Foo 上调用它来定义 instance_bar 方法时,instance_bar 就变成了一个可以通过“Foo.instance_bar”调用的类方法。 很明显,这段代码没有创建实例方法,因为 Foo.new.instance_bar 导致“未定义的方法'instance_bar'”。
为什么instance_eval在此上下文中定义类方法而不是实例方法?
Foo = Class.new
Foo.instance_eval do
def instance_bar
"instance_bar"
end
end
puts Foo.instance_bar #=> "instance_bar"
puts Foo.new.instance_bar #=> undefined method ‘instance_bar’
My understanding is that calling instance_eval on an object is supposed to allow you to define an instance variable or method for that object.
But in the example above, when you call it on class Foo to define the instance_bar method, instance_bar becomes a class method that can be invoked with "Foo.instance_bar". It is clear that this code has not created an instance method because Foo.new.instance_bar results in "undefined method ‘instance_bar’".
Why does instance_eval define a class method rather than an instance method in this context?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
x.instance_eval
会更改您的上下文,因此self
的计算结果为x
。这允许您做很多事情,包括定义实例变量和实例方法,但仅限于 x。
Ruby 允许您在几个位置为对象定义实例方法。 通常情况下,
人们在类中定义它们,并且这些实例方法在所有实例之间共享
该类的(如上面的
def var
)。然而,我们也可以为单个对象定义一个实例方法:
即使
x
和y
具有相同的类,它们也不共享这些方法,因为它们是仅为x
定义。现在在 Ruby 中,一切都是对象,甚至是类。 类方法只是实例方法
对于该类对象。
再次注意,所有这些方法都是
A
特定的,B
无法访问它们中的任何一个:这里要注意的重要一点是
类方法只是类
Class
的对象的实例方法x.instance_eval
changes your context soself
evaluates tox
.This allows you to do many things, including defining instance variables and instance methods but only for x.
Ruby lets you define instance methods for an object in a couple places. Normally,
one defines them in a class, and those instance methods are shared among all instances
of that class (like
def var
above).However, we can also define an instance method for just a single object:
Even though
x
andy
have the same class, they don't share these methods, since they were only defined forx
.Now in ruby, everything's an object, even classes. Class methods are just instance methods
for that class object.
Note again, that all these methods are
A
-specific,B
doesn't get access to any of them:The important thing to take away from here is that
class methods are just instance methods of an object of class
Class
“instance_eval”的目的是扩展对象,而“class_eval”的目的是扩展类。 由于类也是对象,因此您可以对类应用instance_eval。
我想类的扩展在经典的 OOP 中更容易理解。 动态语言使我们能够轻松地指定特定对象的行为。 事实上,每个对象都可以有自己的行为,这为应用程序设计增加了很大的灵活性。 对于同一类的对象来说,不仅数据会有所不同。 两个人的不同不仅因为他们出生的年份不同,不仅因为他们有不同的父母,而且他们的想法不同,因此行为也不同。
改变每个对象的行为的能力是基础。 它存在于多种语言中。
考虑instance_eval 首先考虑对象。 然后您将意识到类也是对象 - 对象的附加目的是创建新对象,以保存常见行为(方法)的描述。 您不仅可以使用类的定义,还可以将类分配给变量,将类作为参数传递,调用类上的方法,对类进行编程!
我会推荐 Yehuda Katz 和 Yugui 撰写的文章来深入研究它:
The purpose of 'instance_eval' is to extend objects, but the purpose of 'class_eval' is to extend classes. And because classes are also objects, you can apply instance_eval on classes.
I guess that extending of classes is just more understandable in classic OOP. Dynamic languages allow us to easily specify behaviour of particular objects. Fact that each object can have own behaviour adds a lot of flexibility designing an application. Not only data can vary for objects of the same class. Two humans differ not only because they were born in different years, not only because they have different parents but they can think different and thus behave different.
Ability to change the behaviour of each object is fundamental. It exists in many languages.
Thinking about instance_eval think about objects first. Then you'll realize that classes are also objects - objects which additional purpose to create new objects, to hold description of common behaviour (methods). You can not only use definition of a class, but can also assign class to a variable, pass class as an argument, call method on a class, program a class!
I would recommend articles written by Yehuda Katz and Yugui to dive deeper into it: