【问题标题】:In Ruby are there any related applications of the syntax: class << self ... end在Ruby中有没有相关的语法应用:class << self ... end
【发布时间】:2010-10-28 03:27:36
【问题描述】:
class << self
attr_accessor :n, :totalX, :totalY
end

上面的语法用于定义类实例变量。但是当我想到语法意味着什么时,它对我来说没有任何意义,所以我想知道这种语法是否用于任何其他类型的定义。我的困惑点是:

class << self

附加操作符通常意味着“将右侧的内容添加到左侧的对象”。但是在这个块的上下文中,怎么加起来就是“把这个块的内容放到类实例的定义中而不是实例中”呢?

出于同样的原因,我很困惑为什么在一个上下文中类

class Point
  # Instance methods go here
  class << self
    # Class methods go here
  end
end

【问题讨论】:

    标签: ruby class-variables class-method instance-methods class-instance-variables


    【解决方案1】:

    在 Ruby 中,您可以重新打开现有的类并添加方法。也就是说,你可以说:

    class Foo
      def bob
        return "hello from bob"
      end
    end
    

    这些方法存储在Foo-class 的内部字典(可能是实例变量)的某个位置(它只是Class-class 的一个实例,因此 个实例变量)

    但令人惊讶的是,您还可以向现有对象的实例添加方法

    foo = Foo.new
    foo2 = Foo.new
    
    def foo.fred
      return "I am fred"
    end
    
    
    foo.fred  #=> "I am fred"
    foo2.fred #=> NoMethodError
    

    但是这个方法实际存储在哪里

    原来 Ruby 在后台创建了一个新类(有时称为 singleton classmetaclasseigenclass),它被插入到继承中Foo-class 及其实例之间的层次结构

    所以继承关系是这样的:

    foo < (eigenclass of foo) < Foo < Class
    

    (如果你说 foo.superclass 你不会看到单例类)

    class &lt;&lt; X-syntax 是一种进入这个特殊类的方法,这样你就可以直接操作它。以下代码块完全相同:

    def foo.bar
      return "xy"
    end
    
    # is exactly the same as
    
    class << foo
      def bar
        return "xy"
      end
    end
    

    所以class Foo &lt; Barclass &lt;&lt; Foo 之间的相似性并非偶然,两者都存在继承。

    class &lt;&lt; X 视为“打开X 的元类”

    在 Ruby 中要记住的是,类本身就是对象。 (Class 类的实例)所以如果你说:

    class Foo
      class << self
        def k
          return "x"
        end
      end
    end
    

    self 在此代码块中绑定到Foo)所以kFoo 的特征类的实例方法,这使它成为@987654340 的类方法@

    所有这一切在chapter about classes of the Pickaxe(不幸的是网络版不包含图表)和_whys Seeing Metaclasses Clearly中都有更清楚的解释

    【讨论】:

      【解决方案2】:

      将类视为包含成员的字典,其中包括所有访问器和实例变量。当您告诉班级“附加”到“自身”时,您是在说“将这些添加到班级成员的字典中”。

      我承认这个符号有点古怪。

      【讨论】:

      • 好的——这是一个很好的观察方式——这个类实际上是一本字典。但实际上你在我添加我的最后一个例子之前回答了,在另一个上下文中,相同的语法(根据我正在阅读的书)产生类方法而不是类实例方法。为什么底部的 Point 类示例会生成类方法,而顶部的 attr_accessor 会为您提供类实例级别的属性?
      • 实际上使用您给出的解释也许我可以回答我之前评论中的问题 - attr_accessor 方法调用 Class 类的 instance_variable_set 和 instance_variable_get 方法。通常这些会导致创建实例变量,但是因为我们正在添加到类字典中,正如你所说的,我们正在创建类实例变量。好的,我想我现在明白了。谢谢。
      • -1 误导,因为 class
      • 因为,当然,向定义类的元类添加信息实际上并不是向类添加东西,而是向定义类的元类添加信息,从而改变类。是的。
      【解决方案3】:

      从“附加”运算符的角度来考虑它实际上是令人困惑的。更好的看待它的方式是,就像class Foo 打开类 Foo 一样,也就是将 'self' 设置为类对象 Foo,必要时创建它,所以 class &lt;&lt; self 打开当前 ' 的 eigenclass自己的对象。请注意,它不限于 self - 对于任何对象 bar,您可以说 class

      class A
        def hello
          print "hello world"
        end
      end
      
      a = A.new
      b = A.new
      
      class << a
        def goodbye
          print "goodbye cruel world"
        end
      end
      
      a.hello
      b.hello
      a.goodbye
      b.goodbye
      

      【讨论】:

        猜你喜欢
        • 2020-03-07
        • 1970-01-01
        • 1970-01-01
        • 2022-01-16
        • 1970-01-01
        • 2014-01-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多