Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby 类对象,单例类_Ruby_Oop_Metaprogramming - Fatal编程技术网

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指向单

我用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
指向单例类的上下文? 这表示
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_变量#=>[]

现在,如果你用class
class
替换class
A
,用object
Klass
替换object
A
(在这种特殊情况下,只不过是class
class
)我希望你能对你的问题得到解释。如果您还有问题,请随意提问。

编辑了这个问题,用官方术语“singleton类”替换“eigenclass”。非常感谢!另外,我认为你应该从复习课上回来,写一篇关于其他人上课的文章!我离问题=)太远了,不过,它最有价值的部分以更结构化的形式出现在这个版本中,所以我认为它是可以的。另外,你会说俄语吗?我可以通过gtalk与您交谈吗?@avy,是的,我会说俄语,但我对私人咨询公司不太感兴趣=)