966

class << selfRuby中做什么?

4

6 回答 6

981

首先,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指的是调用函数的对象。在这种情况下,class << 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

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

于 2010-03-24T03:05:37.750 回答
47

我找到了一个超级简单的解释class << selfEigenclass以及不同类型的方法。

在 Ruby 中,可以将三种类型的方法应用于类:

  1. 实例方法
  2. 单例方法
  3. 类方法

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

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

Eigenclass访问 an (包括单例方法)的另一种方法是使用以下语法 ( 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
于 2016-01-29T11:37:45.450 回答
35

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

Ruby 将方法存储在类中,所有方法都必须与一个类相关联。定义单例方法的对象不是类(它是类的实例)。如果只有类可以存储方法,那么对象如何存储单例方法?创建单例方法时,Ruby 会自动创建一个匿名类来存储该方法。这些匿名类称为元类,也称为单例类或特征类。单例方法与元类相关联,而元类又与定义了单例方法的对象相关联。

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

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'…

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

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

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

所有对象都可能有元类。这意味着类也可以有元类。在上面的示例中, class << self 修改了 self ,因此它指向 Zabuton 类的元类。当一个方法在没有显式接收者(将在其上定义该方法的类/对象)的情况下定义时,它被隐式定义在当前范围内,即 self 的当前值。因此,stuff 方法是在 Zabuton 类的元类中定义的。上面的例子只是定义类方法的另一种方式。恕我直言,最好使用 def self.my_new_clas_method 语法来定义类方法,因为它使代码更容易理解。上面的例子被包括在内,所以我们理解当我们遇到 class << self 语法时发生了什么。

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

于 2016-06-26T18:17:36.190 回答
19

什么类 << 事情做了:

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

[它 self == thing.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对象从其继承#methods#singleton_class.instance_methods然后从其继承#class.instance_methods
这里我们给出了单例类hi的实例方法。它可以用class << hi代替。有所有的实例方法,可能还有更多(这里)。:a
hi#singleton_classhi#class:a

[事物的实例方法 #class #singleton_class 可以直接应用于事物。当 ruby​​ 看到 thing.a 时,它首先在 thing.singleton_class.instance_methods 中查找 :a 方法定义,然后在 thing.class.instance_methods 中查找]


顺便说一句 - 他们称对象的单例类== metaclass == eigenclass

于 2015-11-12T14:03:13.070 回答
4

А单例方法是只为单个对象定义的方法。

例子:

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 的 Singleton 方法

测试


单例的 test_obj 方法

测试_2

测试_3

于 2016-09-15T18:50:59.937 回答
1

事实上,如果您为 Ruby 项目编写任何 C 扩展,那么实际上只有一种方法可以定义 Module 方法。

rb_define_singleton_method

我知道这种自营业务只会引发各种其他问题,因此您可以通过搜索每个部分来做得更好。

先说对象。

foo = Object.new

我可以为 foo 做一个方法吗?

当然

def foo.hello
 'hello'
end

我该怎么办?

foo.hello
 ==>"hello"

只是另一个对象。

foo.methods

你得到所有的 Object 方法加上你的新方法。

def foo.self
 self
end

foo.self

只是 foo 对象。

Try to see what happens if you make foo from other Objects like Class and Module. The examples from all the answers are nice to play with but you have to work with different ideas or concepts to really understand what is going on with the way the code is written. So now you have lots of terms to go look at.

Singleton, Class, Module, self, Object, and Eigenclass was brought up but Ruby doesn't name Object Models that way. It's more like Metaclass. Richard or __why shows you the idea here. http://viewsourcecode.org/why/hacking/seeingMetaclassesClearly.html And if the blows you away then try looking up Ruby Object Model in search. Two videos that I know of on YouTube are Dave Thomas and Peter Cooper. They try to explain that concept too. It took Dave a long time to get it so don't worry. I'm still working on it too. Why else would I be here? Thanks for your question. Also take a look at the standard library. It has a Singleton Module just as an FYI.

This is pretty good. https://www.youtube.com/watch?v=i4uiyWA8eFk

于 2017-05-08T13:29:47.767 回答