gpt4 book ai didi

ruby - 为什么在类上调用 instance_eval() 时定义类方法?

转载 作者:数据小太阳 更新时间:2023-10-29 07:12:33 25 4
gpt4 key购买 nike

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在对象上应该允许您为该对象定义实例变量或方法。

但是在上面的例子中,当你在类 Foo 上调用它来定义 instance_bar 方法时,instance_bar 变成了一个可以用“Foo.instance_bar”调用的类方法。很明显这段代码没有创建实例方法,因为 Foo.new.instance_bar 导致“undefined method ‘instance_bar’”。

为什么 instance_eval 在此上下文中定义类方法而不是实例方法?

最佳答案

x.instance_eval 更改您的上下文,因此 self 的计算结果为 x

这允许您做很多事情,包括定义实例变量和实例方法,但仅限于 x。

 x = Object.new
y = Object.new

# define instance variables for x and y
x.instance_eval { @var = 1 }
y.instance_eval { @var = 2 }

# define an instance method for all Objects
class Object
def var
@var
end
end

x.var #=> 1
y.var #=> 2

Ruby 允许您在几个地方为一个对象定义实例方法。一般,一个在类中定义它们,并且这些实例方法在所有实例之间共享该类的(如上面的 def var)。

但是,我们也可以只为单个对象定义一个实例方法:

# here's one way to do it
def x.foo
"foo!"
end
# here's another
x.instance_eval do
# remember, in here self is x, so bar is attached to x.
def bar
"bar!"
end
end

尽管 xy 具有相同的类,但它们不共享这些方法,因为它们仅为 x 定义。

x.foo #=> "foo!"
x.bar #=> "bar!"
y.foo #=> raises NoMethodError
y.bar #=> raises NoMethodError

现在在 ruby​​ 中,一切都是对象,甚至是类。类方法只是实例方法对于那个类对象。

# we have two ways of creating a class:
class A
end
# the former is just syntatic sugar for the latter
B = Class.new

# we have do ways of defining class methods:

# the first two are the same as for any other object
def A.baz
"baz!"
end
A.instance_eval do
def frog
"frog!"
end
end

# the others are in the class context, which is slightly different
class A
def self.marco
"polo!"
end
# since A == self in here, this is the same as the last one.
def A.red_light
"green light!"
end

# unlike instance_eval, class context is special in that methods that
# aren't attached to a specific object are taken as instance methods for instances
# of the class
def example
"I'm an instance of A, not A itself"
end
end
# class_eval opens up the class context in the same way
A.class_eval do
def self.telegram
"not a land shark"
end
end

再次注意,所有这些方法都是 A 特定的,B 无法访问其中任何一个:

A.baz #=> "baz!"
B.telegram #=> raises NoMethodError

这里最重要的是类方法只是类 Class

对象的实例方法

关于ruby - 为什么在类上调用 instance_eval() 时定义类方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/900704/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com