一个类和Ruby中该类的单例有什么区别?

好吧,所以我想在Ruby中做一些元编程,我有点困惑。 根据我读过的几篇文章(像这一篇 ),为了动态地将类方法添加到Ruby类中,你必须使用类的单例类:

class Klass end class << Klass self.define_method(:foo) { return "foo" } end 

这是为什么,与此有何不同?

 class Klass self.define_method(:foo) { return "foo" } end 

(对不起,如果这个问题包含任何错误的假设。就像我说的那样,我有点困惑。)

直接回答您的问题: Module#define_method创建一个实例方法。 “类方法”是Class对象的单例类(或本征类)上的实例方法。 我确信这听起来很混乱。 让我解释为什么Ruby首先包含“单例类”的概念:

首先,我要说的是,不同面向对象语言的基本“框架”是多种多样的。 关于对象,类,元类等的Ruby设计绝不是唯一可能的设计,并且语言可能以不同的方式设计。 话虽如此,Ruby的工作方式仍然存在逻辑上的原因。 我会尽量简明扼要地解释……

想想一个简单的方法调用,如:

 [1,2,3].first 

这里我们调用一个名为first的方法,将Array对象作为接收器。 要处理此方法调用,Ruby需要搜索匹配的方法定义并执行它。 它从哪里开始寻找? 当然,在Array的实例方法中。 如果它没有找到它,它将查看Array的超类,然后是超类的超类,以及混合到Array或其超类中的Module等。

“基于类”(与基于原型相对)的面向对象语言都或多或少地以这种方式工作。 如果您曾使用Java,C ++或Python编程,那么您应该熟悉这种行为。

现在,Ruby的创建者也希望能够将方法添加到一个对象中。 在基于原型的OO语言中,这很容易,但它如何在基于类的语言中工作? 他通过引入“单身类”或“特征类”的概念使其成为可能。

简单地说,“单例类”只是一个只有一个实例的类。 我相信,不是试图跟踪每个单个对象的不同单例类,Ruby会等到第一次尝试访问对象的单例类,然后创建类并将其动态插入到对象的inheritance链中。

正如我刚才所说,当一个方法被调用时,Ruby首先在对象的类中查找匹配的定义,然后是超类等。因为单例类是作为对象的inheritance链中的第一个链接插入的,所以它们是第一个哪个Ruby会查找方法定义。

引入“单身类”的概念也同时解决了另一个问题。 在Java(例如)中,您可以定义在类上调用的static方法。 在Ruby中,人们经常想做类似的事情。 使用“单例”类和方法,您可以做到这一点:您所要做的就是在Class对象上定义一个单例方法。

(请记住,类也是 Ruby中的对象。这就是为什么“单例”类和方法的概念可以“一石二鸟”,正如我在上面解释的那样!)

额外的信息:

一开始,我提到了“实例方法”。 我不知道这是否会令人困惑,或者您是否已经知道“实例方法”是什么。 当你定义一个Ruby类时,就像这样……

 class MyClass def my_method # do something end end 

…然后my_method将被添加为MyClass实例方法 。 当Ruby在对象的类,超类等中搜索方法定义时,它实际看到的是它们的实例方法 。 所以对象的“方法”是它的类的实例方法,加上超类的实例方法,超类的超类等。

关于单例类如何与Ruby中的方法查找交互,有一点点不一致,我上面没有提到。 如果你想详细了解:

Singleton类的类对象通常与其他对象的singleton类略有不同。 如果你有一个inheritance自另一个B类的A类,而B有单例方法, A会inheritance实例方法,还会inheritanceB的单例方法。 换句话说, B的单例类被视为A的单例类的超类。 任何其他对象的单例类都不是这样。