在Ruby中有任何相关的语法应用程序:class << self ... end

pez*_*ser 11 ruby class-method class-variables class-instance-variables instance-methods

class << self
attr_accessor :n, :totalX, :totalY
end
Run Code Online (Sandbox Code Playgroud)

上面的语法用于定义类实例变量.但是当我考虑语法含义时,它对我没有任何意义,所以我想知道这种类型的语法是否用于任何其他类型的定义.我在这里的困惑是:

class << self
Run Code Online (Sandbox Code Playgroud)

追加运算符通常意味着"向左侧的对象添加右侧的内容".但是在这个块的上下文中,如何将"将此块的内容放入类实例的定义而不是实例"?

出于同样的原因,我很困惑为什么在一个上下文类中,<< self可以定义类实例变量,而在另一个上下文它似乎创建了类变量,例如:

class Point
  # Instance methods go here
  class << self
    # Class methods go here
  end
end
Run Code Online (Sandbox Code Playgroud)

lev*_*lex 19

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

class Foo
  def bob
    return "hello from bob"
  end
end
Run Code Online (Sandbox Code Playgroud)

这些方法存储在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
Run Code Online (Sandbox Code Playgroud)

这种方法实际存储在哪里

事实证明Ruby在幕后创建了一个新类(有时称为单例类,元类或本),它被插入到-class与其实例之间的继承层次中Foo.

所以继承关系看起来像这样:

foo < (eigenclass of foo) < Foo < Class
Run Code Online (Sandbox Code Playgroud)

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

class << X-syntax是一种方式来获得这种特殊的班级,这样就可以直接操作它.以下代码块完全等效:

def foo.bar
  return "xy"
end

# is exactly the same as

class << foo
  def bar
    return "xy"
  end
end
Run Code Online (Sandbox Code Playgroud)

所以之间的相似class Foo < Barclass << Foo不是偶然的,有传承在这两个事情.

想象class << X为"打开X的元类"

在Ruby中要记住的事情是类本身只是对象.(班级实例Class)如果你说:

class Foo
  class << self
    def k
      return "x"
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

(在此代码块中self绑定Foo)因此k是本征类的实例方法Foo,这使得它成为一个类方法Foo

所有这些都在关于Pickaxe的类章节中更清楚地解释了(不幸的是,Web版本不包含图表)和_whys 明显看到Metaclasses