我知道单例方法存在于单例类(或特征类)中。我的第一个问题是:
为什么他们不能住在物体内?我知道在红宝石中,一个物体可以 只保存实例变量。但我看不出为什么单身方法 不是设计成对象。
接下来,
如果对象只能包含实例变量,那么为什么类, 哪些是Class的对象,是否能够存储方法?
我只是在概念层面感到困惑。我已多次阅读过ruby对象模型的一致性。
答案 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
,但没有出现,因为Foo
是Class
的一个实例,所以它不应该存储
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!