红宝石中的单身方法

时间:2013-05-17 18:23:47

标签: ruby

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

  

为什么他们不能住在物体内?我知道在红宝石中,一个物体可以   只保存实例变量。但我看不出为什么单身方法   不是设计成对象。

接下来,

  

如果对象只能包含实例变量,那么为什么类,   哪些是Class的对象,是否能够存储方法?

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

4 个答案:

答案 0 :(得分:2)

广告1,他们确实居住在一个物体内。事实上, Singleton类只是一种心理构造。 'Singleton'在这里意味着,根据定义,该类只有一个实例 - 该对象。所以对象和单例类的身份是不可分割的相同。

Ad 2,答案是,因为Matz决定如此。更确切地说,不是类,而是模块(Module类)存储方法,以及Class < Module

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

o = Object.new
o.singleton_class
o.singleton_class.singleton_class
o.singleton_class.singleton_class.singleton_class
...

答案 1 :(得分:2)

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

因此这些方法仍然存在于类中,但您无法创建该类的另一个实例。

类是一个对象,但由于它作为其他对象(自己的实例)的模板,因此它将实例方法保存在其模块中。但是如果你把一个类视为一个普通的对象,例如在它上面调用#object_id,它就会给你正常对象所需的所有行为。

答案 2 :(得分:1)

  

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

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

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

Class.instance_methods(true).grep(/^sup/)
#=>[:superclass]

答案 3 :(得分:1)

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

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

Fred = MyPetObjectThatCanStoreMethods.new

因此,Fred不是一个模块,而是来自Module的decsend,因此能够存储方法和常量:

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 存储 #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!