pez*_*ser 5 ruby class-method instance-method
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’
Run Code Online (Sandbox Code Playgroud)
我的理解是,在对象上调用instance_eval应该允许您为该对象定义实例变量或方法.
但是在上面的示例中,当您在类Foo上调用它来定义instance_bar方法时,instance_bar将成为可以使用"Foo.instance_bar"调用的类方法.很明显,这段代码没有创建实例方法,因为Foo.new.instance_bar导致"未定义的方法'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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
尽管x并且y具有相同的类,但它们不共享这些方法,因为它们仅被定义为x.
x.foo #=> "foo!"
x.bar #=> "bar!"
y.foo #=> raises NoMethodError
y.bar #=> raises NoMethodError
Run Code Online (Sandbox Code Playgroud)
现在在红宝石中,一切都是对象,甚至是类.类方法只是该类对象的实例方法.
# 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
Run Code Online (Sandbox Code Playgroud)
再次注意,所有这些方法都是A特定的,B不能访问其中任何一个:
A.baz #=> "baz!"
B.telegram #=> raises NoMethodError
Run Code Online (Sandbox Code Playgroud)
从这里开始,重要的是类方法只是类对象的实例方法 Class
| 归档时间: |
|
| 查看次数: |
1563 次 |
| 最近记录: |