“class << Class”(尖括号)语法的目的是什么?

Mat*_*ski 6 ruby syntax class

为什么我要使用class << Class语法向类添加任何内容?

class Fun
    def much_fun
        # some code here
    end
end

class << Fun # the difference is here!
    def much_more_fun
        # some code here
    end
end
Run Code Online (Sandbox Code Playgroud)

而不是使用猴子修补/鸭打孔方法:

class Fun
    def much_fun
        # some code here
    end
end

class Fun # the difference is here!
    def much_more_fun
        # some code here
    end
end
Run Code Online (Sandbox Code Playgroud)

在阅读Why's Poignant Guide to Ruby 时,我遇到了:

为什么定义一个类LotteryDraw

class LotteryDraw
    # some code here
    def LotteryDraw.buy( customer, *tickets )
        # some code here as well
    end
end
Run Code Online (Sandbox Code Playgroud)

过了一会儿,向LotteryDraw类添加了一个方法:

class << LotteryDraw
    def play
        # some code here
    end
end
Run Code Online (Sandbox Code Playgroud)

说:

当你看到class << obj,相信你的内心时,我直接添加到 的定义中obj

这个语法的目的是什么?为什么为什么决定这样做而不是使用猴子修补方法?


这些是一些相关的问题和网站:

Bro*_*tse 4

需要更多解释。在 ruby​​ 中,几乎每个对象都可以创建一个奇怪的东西,称为实例类。这个东西就像一个普通的类,主要区别在于它只有一个实例,并且该实例是在该类之前创建的。

简而言之,拥有 A 级,您可以:

a = A.new
b = A.new
Run Code Online (Sandbox Code Playgroud)

和现在都是类 A 的实例,并且可以访问该类中定义的所有实例方法ab现在假设我们要添加一个额外的方法,该方法只能由 访问a,但不能由 访问b(这在某些情况下可能有用,但如果可能的话应避免使用)。所有的方法都是在类中定义的,所以我们似乎需要将它添加到类 A 中,但这样它也可以被访问b。在这种情况下,我们需要为a对象创建一个实例类。为此,我们使用class << <object>语法:

class << a
  def foo
  end
end

a.foo #=> nil
b.foo #=> undefined method
Run Code Online (Sandbox Code Playgroud)

简而言之,class << <object>为给定对象打开一个实例类,允许为给定实例定义附加实例方法,这些方法在任何其他对象上不可用。

现在,话虽这么说:在 Ruby 中,类只是 Class 类的实例。这:

class A
end
Run Code Online (Sandbox Code Playgroud)

几乎相当于(这里的差异并不重要)

A = Class.new
Run Code Online (Sandbox Code Playgroud)

因此,如果类是对象,它们就可以创建它们的实例类。

class << A
  def foo
  end
end

A.foo  #=> nil
Class.new.foo #=> undefined method
Run Code Online (Sandbox Code Playgroud)

它通常用于向给定类添加所谓的类方法,但要点是实际上您是在类的实例类上创建实例方法。

  • 顺便说一句:ISO Ruby 语言规范和核心库都将其称为“单例类”,例如,有 `Object#singleton_class` 方法返回对象的单例类。 (2认同)