3

我知道单例方法存在于单例类(或特征类)中。我的第一个问题是:

为什么它们不能生活在物体内部?我知道在 ruby​​ 中,一个对象只能保存实例变量。但我不明白为什么单例方法没有设计成对象。

下一个,

如果对象只能包含实例变量,那么作为 Class 的对象的类怎么能存储方法呢?

我只是在概念层面上感到困惑。我读过很多次 ruby​​ 对象模型是一致的。

4

4 回答 4

2

广告 1,它们确实存在于对象内部。事实上,单例类只是一种心理结构。这里的“单例”意味着,根据定义,该类只有一个实例——那个对象。所以对象的身份和单例类是密不可分的。

广告 2,答案是,因为 Matz 如此决定。更准确地说,不是类,而是模块(Module 类)存储方法,并且Class < Module.

您可能会感兴趣,默认情况下不实例化对象的单例类。在您尝试访问它之前,它根本不存在。这是因为如果所有单例类都立即实例化,您将拥有一个无限的单例类链:

o = Object.new
o.singleton_class
o.singleton_class.singleton_class
o.singleton_class.singleton_class.singleton_class
...
于 2013-05-17T18:36:27.000 回答
2

单例模式的目标是确保特定类中只有一个对象存在于系统中。

所以这些方法仍然存在于一个类中,但是您不能创建该类的另一个实例。

一个类是一个对象,但是因为它作为其他对象的模板,它自己的实例,它把它们的实例方法保存在它的模块中。但是,如果您将一个类视为普通对象,例如调用#object_id它,它会为您提供普通对象所期望的所有行为。

于 2013-05-17T18:37:53.410 回答
1

Module继续我们在评论中的讨论:严格来说,存储方法(和常量)的能力是模块(类)的内置特殊能力。Classclass 恰好是 class 的子Module类,这使得它继承了模块存储方法的能力,但是您可以自由地创建具有该能力的其他对象(不仅仅是类):

class MyPetObjectThatCanStoreMethods < Module
  def greet; puts "Bow, wow!" end
end

Fred = MyPetObjectThatCanStoreMethods.new

因此,Fred它不完全是一个模块,而是来自Module并具有存储方法和常量的能力:

module Fred # this is allowed!
  LENGTH = 19
  def rise; puts "I'm rising!" end
end

您不能对普通对象执行此操作,只能使用模块后代!

Fred::LENGTH #=> 19
Fred.greet
#=> Bow, wow!
Fred.rise
#=> NoMethodError

那是因为Fred stores #rise方法,就像模块一样,但不像#greet方法,#rise不是它的实例方法!为了访问它,我们必须Fred在一个合适的类中包含:

o = Object.new
o.rise
#=> NoMethodError
class << o  # Including Fred in the metaclass of o
  include Fred
end
o.rise
#=> I'm rising!
于 2013-05-17T19:41:12.567 回答
1

如果对象只能包含实例变量,那么作为 Class 的对象的类怎么能存储方法呢?

class Foo
  def suprim;end
end
Foo.instance_methods(true).grep(/^sup/)
#=> [:suprim]

我搜索了Class的实例方法superclass,但没有出现,因为Foo是的实例Class,所以它不应该存储的实例方法Class。但是,是的,Foo只返回要使用的实例的方法。这是自然的。现在看下面:

Class.instance_methods(true).grep(/^sup/)
#=>[:superclass]
于 2013-05-17T18:42:12.770 回答