类<< self在Ruby中做什么?


当前回答

首先,class << foo语法打开了foo的单例类(eigenclass)。这允许您对特定对象上调用的方法的行为进行专门化。

a = 'foo'
class << a
  def inspect
    '"bar"'
  end
end
a.inspect   # => "bar"

a = 'foo'   # new object, new singleton class
a.inspect   # => "foo"

现在,回答这个问题:class << self打开了self的单例类,这样就可以为当前self对象(在类或模块体中是类或模块本身)重新定义方法。通常,这用于定义类/模块(“静态”)方法:

class String
  class << self
    def value_of obj
      obj.to_s
    end
  end
end

String.value_of 42   # => "42"

这也可以写成一种速记:

class String
  def self.value_of obj
    obj.to_s
  end
end

或者更短:

def String.value_of obj
  obj.to_s
end

在函数定义中,self指向调用函数的对象。在这种情况下,类<< self打开该对象的单例类;其中一个用途是实现一个穷人的状态机:

class StateMachineExample
  def process obj
    process_hook obj
  end

private
  def process_state_1 obj
    # ...
    class << self
      alias process_hook process_state_2
    end
  end

  def process_state_2 obj
    # ...
    class << self
      alias process_hook process_state_1
    end
  end

  # Set up initial state
  alias process_hook process_state_1
end

因此,在上面的示例中,StateMachineExample的每个实例都有别名为process_state_1的process_hook,但注意在后者中,它可以将process_hook(仅用于自身,不影响其他StateMachineExample实例)重新定义为process_state_2。因此,每次调用者调用process方法(该方法调用可重定义的process_hook)时,行为都会根据它所处的状态而改变。

其他回答

首先,class << foo语法打开了foo的单例类(eigenclass)。这允许您对特定对象上调用的方法的行为进行专门化。

a = 'foo'
class << a
  def inspect
    '"bar"'
  end
end
a.inspect   # => "bar"

a = 'foo'   # new object, new singleton class
a.inspect   # => "foo"

现在,回答这个问题:class << self打开了self的单例类,这样就可以为当前self对象(在类或模块体中是类或模块本身)重新定义方法。通常,这用于定义类/模块(“静态”)方法:

class String
  class << self
    def value_of obj
      obj.to_s
    end
  end
end

String.value_of 42   # => "42"

这也可以写成一种速记:

class String
  def self.value_of obj
    obj.to_s
  end
end

或者更短:

def String.value_of obj
  obj.to_s
end

在函数定义中,self指向调用函数的对象。在这种情况下,类<< self打开该对象的单例类;其中一个用途是实现一个穷人的状态机:

class StateMachineExample
  def process obj
    process_hook obj
  end

private
  def process_state_1 obj
    # ...
    class << self
      alias process_hook process_state_2
    end
  end

  def process_state_2 obj
    # ...
    class << self
      alias process_hook process_state_1
    end
  end

  # Set up initial state
  alias process_hook process_state_1
end

因此,在上面的示例中,StateMachineExample的每个实例都有别名为process_state_1的process_hook,但注意在后者中,它可以将process_hook(仅用于自身,不影响其他StateMachineExample实例)重新定义为process_state_2。因此,每次调用者调用process方法(该方法调用可重定义的process_hook)时,行为都会根据它所处的状态而改变。

什么类<< thing做:

class Hi
  self #=> Hi
  class << self #same as 'class << Hi'
    self #=> #<Class:Hi>
    self == Hi.singleton_class #=> true
  end
end

[它使自己==东西。]Singleton_class在它的块的上下文中]。


什么是thing.singleton_class?

hi = String.new
def hi.a
end

hi.class.instance_methods.include? :a #=> false
hi.singleton_class.instance_methods.include? :a #=> true

Hi对象从它的#singleton_class继承它的#方法。然后从它的#class.instance_methods。 这里我们给出了hi的单例类实例方法:a。它可以用类<< hi来代替。 Hi 's #singleton_class拥有Hi 's #class拥有的所有实例方法,可能还有更多(:a here)。

[事物的#class和#singleton_class的实例方法可以直接应用于事物。]露比看到的时候。首先,它在thing.singleton_class中查找方法定义。Instance_methods然后在thing。class。Instance_methods中


顺便说一下,他们调用对象的singleton class == metaclass == eigenclass。

通常,实例方法是全局方法。这意味着它们在定义它们的类的所有实例中都可用。相反,单例方法是在单个对象上实现的。

Ruby stores methods in classes and all methods must be associated with a class. The object on which a singleton method is defined is not a class (it is an instance of a class). If only classes can store methods, how can an object store a singleton method? When a singleton method is created, Ruby automatically creates an anonymous class to store that method. These anonymous classes are called metaclasses, also known as singleton classes or eigenclasses. The singleton method is associated with the metaclass which, in turn, is associated with the object on which the singleton method was defined.

如果在单个对象中定义了多个单例方法,则它们都存储在同一个元类中。

class Zen
end

z1 = Zen.new
z2 = Zen.new

class << z1
  def say_hello
    puts "Hello!"
  end
end

z1.say_hello    # Output: Hello!
z2.say_hello    # Output: NoMethodError: undefined method `say_hello'…

在上面的例子中,类<< z1将当前self更改为指向z1对象的元类;然后,它在元类中定义say_hello方法。

类也是对象(称为class的内置类的实例)。类方法不过是与类对象相关联的单例方法。

class Zabuton
  class << self
    def stuff
      puts "Stuffing zabuton…"
    end
  end
end

All objects may have metaclasses. That means classes can also have metaclasses. In the above example, class << self modifies self so it points to the metaclass of the Zabuton class. When a method is defined without an explicit receiver (the class/object on which the method will be defined), it is implicitly defined within the current scope, that is, the current value of self. Hence, the stuff method is defined within the metaclass of the Zabuton class. The above example is just another way to define a class method. IMHO, it's better to use the def self.my_new_clas_method syntax to define class methods, as it makes the code easier to understand. The above example was included so we understand what's happening when we come across the class << self syntax.

更多关于Ruby类的信息可以在这篇文章中找到。

我发现了一个超级简单的解释类<< self,本征类和不同类型的方法。

在Ruby中,有三种类型的方法可以应用到一个类:

实例方法 单例方法 类方法

实例方法和类方法几乎与其他编程语言中的同名方法相似。

class Foo  
  def an_instance_method  
    puts "I am an instance method"  
  end  
  def self.a_class_method  
    puts "I am a class method"  
  end  
end

foo = Foo.new

def foo.a_singleton_method
  puts "I am a singletone method"
end

另一种访问本征类(包括单例方法)的方法是使用以下语法(class <<):

foo = Foo.new

class << foo
  def a_singleton_method
    puts "I am a singleton method"
  end
end

现在你可以为self定义一个单例方法,它是类Foo本身在这个上下文中:

class Foo
  class << self
    def a_singleton_and_class_method
      puts "I am a singleton method for self and a class method for Foo"
    end
  end
end

А singleton方法是仅为单个对象定义的方法。

例子:

class SomeClass
  class << self
    def test
    end
  end
end

test_obj = SomeClass.new

def test_obj.test_2
end

class << test_obj
  def test_3
  end
end

puts "Singleton's methods of SomeClass"
puts SomeClass.singleton_methods
puts '------------------------------------------'
puts "Singleton's methods of test_obj"
puts test_obj.singleton_methods

SomeClass的单例方法

test


test_obj的单例方法

test_2

test_3