class<< Ruby中的自我成语

时间:2010-03-24 03:02:42

标签: ruby metaclass eigenclass singleton

class << self在Ruby中做了什么?

5 个答案:

答案 0 :(得分:848)

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

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

因此,在上面的示例中,StateMachineExample的每个实例都有process_hook别名为process_state_1,但请注意后者如何重新定义process_hook(for { {1}}仅{1}},不影响其他self实例)StateMachineExample。因此,每次调用者调用process_state_2方法(调用可重新定义的process)时,行为都会根据其所处的状态而变化。

答案 1 :(得分:28)

我在此blog中找到了关于class << selfEigenclass和不同类型的methods的超级简单说明。

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

  1. 实例方法
  2. 单身方法
  3. 班级方法
  4. 实例方法和类方法几乎与其他编程语言中的同义词类似。

    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(包括单例方法)的另一种方法是使用以下语法(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
    

答案 2 :(得分:17)

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

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

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

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

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

所有对象都可能有元类。这意味着类也可以有元类。在上面的例子中,类&lt;&lt; self修饰self,因此它指向Zabuton类的元类。如果定义的方法没有显式接收器(将在其上定义方法的类/对象),则在当前作用域内隐式定义它,即self的当前值。因此,stuff方法是在Zabuton类的元类中定义的。上面的示例只是定义类方法的另一种方法。恕我直言,最好使用def self.my_new_clas_method语法来定义类方法,因为它使代码更容易理解。上面的例子是包含在内的,所以我们理解当我们遇到这个类时发生了什么&lt;&lt;自我语法。

可在this post about Ruby Classes找到其他信息。

答案 3 :(得分:12)

什么类&lt;&lt;事情确实:

ui.bootstrap

[在其阻止的上下文中 class Hi self #=> Hi class << self #same as 'class << Hi' self #=> #<Class:Hi> self == Hi.singleton_class #=> true end end

什么是thing.singleton_class?

self == 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&lt;&lt;嗨代替。
:a hi所有实例方法#singleton_class&#39; s hi都有,可能还有更多(#class此处)。< / p>

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

顺便说一下 - 他们称对象为单例类 == 元类 == 本征类

答案 4 :(得分:3)

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

示例:

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

Someton的SomeClass方法

<强> 测试

Singleton的test_obj方法

<强> test_2

<强> test_3