关于元类:class<>

class << self idiom in Ruby

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


首先,class << foo语法打开foo的singleton类(eigenclass)。这使您能够专门处理对特定对象调用的方法的行为。

1
2
3
4
5
6
7
8
9
10
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的singleton类,这样就可以为当前的self对象(类或模块体内部是类或模块本身)重新定义方法。通常,这用于定义类/模块("静态")方法:

1
2
3
4
5
6
7
8
9
class String
  class << self
    def value_of obj
      obj.to_s
    end
  end
end

String.value_of 42   # =>"42"

这也可以写成一个速记:

1
2
3
4
5
class String
  def self.value_of obj
    obj.to_s
  end
end

或者更短:

1
2
3
def String.value_of obj
  obj.to_s
end

当函数定义内部时,self引用的对象是用函数调用的对象。在这种情况下,class << self为该对象打开了singleton类;它的一个用途是实现穷人的状态机:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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(仅用于self,而不影响其他StateMachineExample实例)到process_state_2。因此,每次调用方调用process方法(调用可重新定义的process_hook方法)时,行为都会根据所处的状态而改变。


我在这个博客中找到了一个关于class << selfEigenclass和不同类型methods的非常简单的解释。

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

  • 实例方法
  • 单子方法
  • 类方法
  • 实例方法和类方法在其他编程语言中几乎相似。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    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 <<

    1
    2
    3
    4
    5
    6
    7
    foo = Foo.new

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

    现在,您可以为self定义一个singleton方法,该方法在本文中是类foo本身:

    1
    2
    3
    4
    5
    6
    7
    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


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

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

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    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<

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

    1
    2
    3
    4
    5
    6
    7
    class Zabuton
      class << self
        def stuff
          puts"Stuffing zabuton…"
        end
      end
    end

    所有对象都可以有元类。这意味着类也可以有元类。在上面的示例中,class<

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


    什么课程<
    1
    2
    3
    4
    5
    6
    7
    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_类?

    1
    2
    3
    4
    5
    6
    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.instance_methods继承其#methods,然后从其#class.instance_methods继承。这里我们给出了hi的单例类实例方法:a。它可以用class<hi的#singleton_class具有hi#class具有的所有实例方法,可能还有更多的实例方法(这里是:a)。

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

    顺便说一句,它们调用对象的单例类==metaclass==eigenclass。


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

    例子:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    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方法

    测试

    单件测试方法

    试验2

    试验3


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

    1
    rb_define_singleton_method

    我知道这个自助业务只会打开其他各种问题,这样你就可以通过搜索每个部分做得更好。

    对象优先。

    1
    foo = Object.new

    我能给foo做个方法吗?

    当然

    1
    2
    3
    def foo.hello
     'hello'
    end

    我该怎么办?

    1
    2
    foo.hello
     ==>"hello"

    只是另一个物体。

    1
    foo.methods

    你得到了所有的对象方法加上你的新方法。

    1
    2
    3
    4
    5
    def foo.self
     self
    end

    foo.self

    只有foo对象。

    尝试看看如果从类和模块等其他对象生成foo会发生什么。所有答案中的例子都很好用,但是你必须用不同的想法或概念来真正理解代码的编写方式。所以现在你有很多条款要看。

    独生子女,类,模块,自我,对象,Eigenclass被提出来了,但Ruby并没有这样命名对象模型。更像是元类。Richard或_uuu为什么在这里向你展示这个想法。http://viewsourcecode.org/why/hacking/seeingmetaclassesclearly.html如果它把你吹走了,那么试着在搜索中查找Ruby对象模型。我在YouTube上知道的两个视频是Dave Thomas和Peter Cooper。他们也试图解释这个概念。戴夫花了很长时间才拿到,所以别担心。我还在努力。不然我为什么会在这里?谢谢你的问题。还可以看看标准库。它有一个单独的模块,就像一个仅供参考。

    这很好。https://www.youtube.com/watch?V= I4UIYWA8EFK