Ruby 类对象,单例类
我用ruby玩元编程,我有一个问题。我有一门课:Ruby 类对象,单例类,ruby,oop,metaprogramming,Ruby,Oop,Metaprogramming,我用ruby玩元编程,我有一个问题。我有一门课: class Klass class << self @x = "yeah" end end b = Klass.new a = class << Klass; self; end a.instance_eval "@x" #=> yeah Klass.instance_eval "@x" #=> nil 另外,解释器中的Klass指向类的上下文,是吗?而a指向单
class Klass
class << self
@x = "yeah"
end
end
b = Klass.new
a = class << Klass; self; end
a.instance_eval "@x" #=> yeah
Klass.instance_eval "@x" #=> nil
另外,解释器中的Klass指向类的上下文,是吗?而a
指向单例类的上下文?
这表示a.class\u eval
和a.instance\u eval
?我有:
a.instance_eval "def pops; puts 0; end"
a.class_eval "def popsx; puts 1; end"
a.pops #=> 0
a.popsx # FAIL
Klass.pops # FAIL
Klass.popsx #=> 1
b.pops; b.popsx # DOUBLE FAIL
我不明白这一点。谢谢 很难完全回答您的问题(要彻底解释Ruby的类模型,请参阅),不过: 使用class\u eval,您实际上定义了实例方法——就好像您在类的主体中一样。例如:
class Klass
end
Klass.class_eval do
def instance_method
puts 'instance method'
end
end
obj = Klass.new
obj.instance_method # instance method
Klass.instance_eval do
def class_method
puts 'class method'
end
end
Klass.class_method # class method
使用instance_eval,您实际上定义了类方法——就好像您在给定对象的singleton(eigenclass)类的主体中一样(当然,在Ruby中类也是对象)。例如:
class Klass
end
Klass.class_eval do
def instance_method
puts 'instance method'
end
end
obj = Klass.new
obj.instance_method # instance method
Klass.instance_eval do
def class_method
puts 'class method'
end
end
Klass.class_method # class method
就你而言:
Klass.instance\u eval“@x”
不起作用,因为@x
不是Klass的一部分,它是Klass的singleton类的一部分:
Klass.instance_eval "def yeah; puts 10; end"
Klass.yeah #=> 10
class Klass
class << self
@x = "yeah"
end
puts @x
end
# prints nothing
Klass.instance\u eval“def yes;put 10;end”
定义了一个“普通”类方法。因此,Klass.yeah
工作正常(请参见上一示例中的Klass.class_方法
)
a.instance\u eval“def pops;put 0;end”
在a
singleton类上定义一个类方法。因此,a.pops
实际上意味着调用pops
类方法(同样,这就像调用Klass.class\u方法一样)
a.popsx
不起作用,因为您必须首先创建a
的实例才能在其上调用popsx(但无法创建singleton类的新实例)
Klass.pops
不起作用,因为在Klass的singleton类中没有定义任何pops
方法(pops
在a
的singleton类中定义)
Klass.popsx
之所以有效,是因为使用a.class_eval“def popsx;put 1;end”
定义了popsx实例方法,然后对Klass对象调用该方法。在某种程度上,它类似于此示例:
class Foo
end
f = class << Foo; self; end
g = class << Foo; self; end
f.instance_eval "def yeah; puts 'yeah'; end"
g.yeah # yeah
g.instance_eval "def ghee; puts 'ghee'; end"
f.ghee # ghee
class Other
end
o = Other.new
Other.class_eval "def yeah; puts 'yeah'; end"
o.yeah # yeah
希望能有所帮助。首先,虽然有些人似乎使用了eigntclass,但singleton类是更常见的术语。Singleton类包含Ruby中对象的特定于对象的行为。除了该单例类所属的原始对象之外,不能创建该类的其他实例
谈到在不同类型的eval中定义方法时,介绍了在instance\u eval
和class\u eval
中定义的方法的好规则:
# class_eval is instance method of Module class
# so it's not available for object a
# a.class_eval { } # => undefined method `class_eval' for #<A:0x8fbaa74>
# instance variable definition works the same inside
# class_eval and instance_eval
A.instance_eval { @y = 1 }
A.class_eval { @z = 1 }
# both variables belong to A class itself
p A.instance_variables # => [:@y, :@z]
# instance variables can be accessed in both ways as well
puts A.instance_eval { @y } # => 1
puts A.class_eval { @z } # => 1
# no instance_variables here
p A.new.instance_variables # => []
这基本上描述了这种情况
有一篇关于类的大量文章,这些类是类的实例,它们的单例类是类的子类,还有一些其他疯狂的东西(与问题没有太大关系)。但由于您的问题可以很容易地应用于常规对象及其类(这使事情更容易解释),所以我决定将其全部删除(不过,您仍然可以在答案的修订历史中看到这些内容)
让我们看看常规类和该类的实例,看看它们是如何工作的:
class A; end
a = A.new
不同类型的评估中的方法定义:
# define instance method inside class context
A.class_eval { def bar; 'bar'; end }
puts a.bar # => bar
puts A.new.bar # => bar
# class_eval is equivalent to re-opening the class
class A
def bar2; 'bar2'; end
end
puts a.bar2 # => bar2
puts A.new.bar2 # => bar2
定义特定于对象的方法:
# define object-specific method in the context of object itself
a.instance_eval { def foo; 'foo'; end }
puts a.foo # => foo
# method definition inside instance_eval is equivalent to this
def a.foo2; 'foo2'; end
puts a.foo2 # => foo2
# no foo method here
# puts A.new.foo # => undefined method `foo' for #<A:0x8b35b20>
现在让我们看看实例变量:
# define instance variable for object a
a.instance_eval { @x = 1 }
# we can access that @x using same instance_eval
puts a.instance_eval { @x } # => 1
# or via convenient instance_variable_get method
puts a.instance_variable_get(:@x) # => 1
现在,在class\u eval
中引用变量:
# class_eval is instance method of Module class
# so it's not available for object a
# a.class_eval { } # => undefined method `class_eval' for #<A:0x8fbaa74>
# instance variable definition works the same inside
# class_eval and instance_eval
A.instance_eval { @y = 1 }
A.class_eval { @z = 1 }
# both variables belong to A class itself
p A.instance_variables # => [:@y, :@z]
# instance variables can be accessed in both ways as well
puts A.instance_eval { @y } # => 1
puts A.class_eval { @z } # => 1
# no instance_variables here
p A.new.instance_variables # => []
#class_eval是模块类的实例方法
#所以它不适用于对象a
#a.class_eval{}#=>的未定义方法'class_eval'#
#实例变量定义在内部工作相同
#类评估和实例评估
A.instance_eval{@y=1}
A.class_eval{@z=1}
#这两个变量都属于一个类本身
p A.instance_variables#=>[:@y,:@z]
#实例变量也可以通过两种方式访问
将A.instance_eval{@y}#=>1
将A.class_eval{@z}{#=>1
#这里没有实例变量
p A.new.instance_变量#=>[]
现在,如果你用classclass
替换classA
,用objectKlass
替换objectA
(在这种特殊情况下,只不过是classclass
)我希望你能对你的问题得到解释。如果您还有问题,请随意提问。编辑了这个问题,用官方术语“singleton类”替换“eigenclass”。非常感谢!另外,我认为你应该从复习课上回来,写一篇关于其他人上课的文章!我离问题=)太远了,不过,它最有价值的部分以更结构化的形式出现在这个版本中,所以我认为它是可以的。另外,你会说俄语吗?我可以通过gtalk与您交谈吗?@avy,是的,我会说俄语,但我对私人咨询公司不太感兴趣=)