首页 文章

在Ruby中的类<< self idiom

提问于
浏览
763

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

6 回答

  • 1

    我在blog找到了一个关于 class << selfEigenclass 和不同类型的 methods 的超级简单解释 .

    在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
    

    访问 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
    
  • 815

    什么类<<东西做:

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

    [it makes** self == thing.singleton_class **in the context of its block] .


    what.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.instance_methods 继承其 #methods ,然后从其 #class.instance_methods 继承 .
    这里我们给了 hisingleton class 实例方法 :a . 它可以用 class << hi 代替 .
    hi#singleton_class 有所有实例方法 hi#class 有,可能还有一些(这里是 :a ) .

    [instance methods of thing's** #class and #singleton_class **can be applied directly to thing. when ruby sees thing.a, it first looks for :a method definition in thing.singleton_class.instance_methods and then in thing.class.instance_methods]


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

  • 12

    首先, 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 对象重新定义方法(在类或模块体内部是类或模块本身) . 通常,这用于定义类/模块("static")方法:

    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 (仅适用于 self ,不影响其他 StateMachineExample 实例)重新定义为 process_state_2 . 因此,每次调用者调用 process 方法(调用可重定义的 process_hook )时,行为都会根据其所处的状态而变化 .

  • 25

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

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

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

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

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

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

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

  • 3

    实际上,如果为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对象 .

    试着看看如果你从其他对象如类和模块中创建foo会发生什么 . 所有答案中的示例都很好用,但您必须使用不同的想法或概念才能真正理解代码编写方式的变化 . 所以现在你有很多术语要看 .

    Singleton,Class,Module,self,Object和Eigenclass被提出来但Ruby并不像Metaclass那样 . 理查德或__why在这里向您展示了这个想法 . http://viewsourcecode.org/why/hacking/seeingMetaclassesClearly.html如果打击你,那么尝试在搜索中查找Ruby对象模型 . 我在YouTube上看到的两个视频是Dave Thomas和Peter Cooper . 他们也试图解释这个概念 . 戴夫需要很长时间才能得到它,所以不要再努力了 . 为什么我会在这里呢?谢谢你的提问 . 另请查看标准库 . 它有一个Singleton模块就像一个FYI .

    这很不错 . https://www.youtube.com/watch?v=i4uiyWA8eFk

  • 12

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

    例:

    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
    

    Singleton的SomeClass方法

    test


    Singleton的test_obj方法

    test_2

    test_3

相关问题