Ruby中的类和该类的单例有啥区别?
Posted
技术标签:
【中文标题】Ruby中的类和该类的单例有啥区别?【英文标题】:What's the difference between a class and the singleton of that class in Ruby?Ruby中的类和该类的单例有什么区别? 【发布时间】:2012-09-07 22:58:28 【问题描述】:好的,所以我正在尝试在 Ruby 中进行一些元编程,但我有点困惑。根据我读过的几篇文章(如this one),为了给Ruby类动态添加类方法,你必须使用类的单例类:
class Klass
end
class << Klass
self.define_method(:foo) return "foo"
end
为什么会这样,和这有什么不同?
class Klass
self.define_method(:foo) return "foo"
end
(对不起,如果这个问题包含任何错误的假设。就像我说的,我有点困惑。)
【问题讨论】:
我认为你应该用 Eigenclass 替换单例。另见***.com/questions/1630815/…。已经有一个***-tag 了。 啊,对了,我忘了它也可以叫Eigenclass。我有什么理由想在“单例类”或“元类”上使用该术语吗? AFAIK "Metaclass" 没问题,但 Singleton 不同。 @knut 但它是一个单例类:(class << Klass; self; end).new
=> TypeError: can't create instance of singleton class
单例类只能有一个实例。特征类只有一个实例(类)。所以一个 Eigenclass 是一个 Singleton 类 - 但不是每个 Singleton 都是一个 Eigenclass。所以我不会在你的具体情况下谈论单例。
【参考方案1】:
直接回答您的问题:Module#define_method
创建一个实例方法。 “类方法”是Class
对象的单例类(或特征类)上的实例方法。我敢肯定这听起来很令人困惑。让我解释一下为什么 Ruby 首先包含“单例类”的概念:
首先,让我说不同面向对象语言的基本“框架”是多种多样的。 Ruby 关于对象、类、元类等的设计绝不是唯一可能的设计,并且语言可以以不同的方式设计。话虽如此,Ruby 以它的方式工作是有逻辑的原因的。我会尽量简明扼要地解释...
想一个简单的方法调用,比如:
[1,2,3].first
这里我们调用了一个名为first
的方法,将Array
对象作为接收者。为了处理这个方法调用,Ruby 需要搜索匹配的方法定义并执行它。它从哪里开始寻找?自然,在Array
的实例方法中。如果没有找到,它会在Array
的超类中查找,然后是超类的超类,以及Module
s,它们混合到Array
或其超类中,等等。
“基于类”(与基于原型相反)的面向对象语言或多或少都以这种方式工作。如果您曾经使用 Java、C++ 或 Python 进行过编程,那么您应该对这种行为很熟悉。
现在,Ruby 的创建者还希望能够为一个对象添加方法。在基于原型的 OO 语言中,这很容易,但它如何在基于类的语言中工作?他通过引入“单例类”或“特征类”的概念使之成为可能。
“单例类”简单来说就是一个只有一个实例的类。我相信,Ruby 不会尝试为 每个 对象跟踪不同的单例类,而是等到您第一次尝试访问对象的单例类,然后创建该类并将其插入对象的继承链是动态的。
正如我刚才所说,当一个方法被调用时,Ruby 首先在对象的类中查找匹配的定义,然后是超类,等等。由于单例类作为 first 链接插入对象的继承链,它们是 Ruby 查找方法定义的第一个位置。
引入“单例类”的概念同时也解决了另一个问题。在 Java 中(例如),您可以定义在类上调用的 static
方法。在 Ruby 中,人们经常想做类似的事情。使用“单例”类和方法,您可以做到这一点:您所要做的就是在 Class 对象上定义一个单例方法。
(请记住,Ruby 中的类也是对象。这就是为什么“单例”类和方法的概念可以“用 1 块石头杀死 2 只鸟”,正如我在上面解释的那样!)
额外信息:
一开始,我提到了“实例方法”。我不知道这是否会令人困惑,或者您是否已经知道“实例方法”是什么。当你定义一个 Ruby 类时,像这样......
class MyClass
def my_method
# do something
end
end
...然后my_method
将被添加为MyClass
的实例方法。当 Ruby 在对象的类、超类等中搜索方法定义时,它实际查看的是它们的实例方法。所以一个对象的“方法”就是它的类的实例方法,加上超类的实例方法、超类的超类等等。
关于单例类如何与 Ruby 中的方法查找交互,有一点我上面没有提到的不一致。如果你想详细了解:
单例类类对象的处理方式与一般其他对象的单例类略有不同。如果你有一个类A
继承自另一个类B
,并且B
有单例方法,A
将不仅继承实例方法,而且也继承@ 的单例方法987654338@。换句话说,B
的单例类被视为A
的单例类的超类。这不适用于任何其他对象的单例类。
【讨论】:
所以你说当我写class A; def self.foo; return "foo"; end; end
时,我实际上是在创建一个名为“A”的Class
的实例和A
的单例类,方法是foo
?
是的!这是完全正确的。实际上,您正在创建一个名为“A”的Class
实例,并将它分配给一个名为A
的常量,并将一个方法foo
添加到@987654348 的单例类中@。 (Ruby 解释器中有一些特殊用途的代码,当您将其分配给常量时,它会自动设置 Class
的名称。试试这个:Abc = Class.new; puts Abc.name
)以上是关于Ruby中的类和该类的单例有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章