单例类
单例方法是属于单个对象的方法。另一方面,单例类(singleton class)则是定义单个对象的类。感到困惑?我也是。那么让我们仔细看看这些令人讨厌的东西…
假设你创建了几十个对象,每个对象都是 Object 类的一个实例。自然的,它们都可以访问 Object 类的常用方法,例如 inspect
和 class
。但是现在你决定只想要一个特殊的对象(为了区别,让我们称之为 ob
),它有一个特殊的方法(让我们称之为 blather
)。
你不希望为此对象定义一个全新的类,因为你永远不会再创建更多拥有 blather
方法的对象。 所以你特别针对 ob
创建了一个类。
你无需为该类命名。你只需要通过在 class 关键字和对象名之间放置一个 <<
符号将它本身附加到 ob
上。然后你可以以通常的方式在类中添加代码:
ob = Object.new
# singleton class
class << ob
def blather( aStr )
puts("blather, blather #{aStr}")
end
end
现在 ob
,并且只有 ob
,不仅拥有 Object 类的所有常用方法;它也拥有了(这里只有 blather
方法,但原则上可以有更多)自己特殊的匿名类(anonymous class)中的方法:
ob.blather( "weeble" ) #=> “blather, blather weeble”
如果你一直在密切关注,你可能已经注意到单例类(singleton class)似乎正在做一些与单例方法(singleton method)类似的事情。使用单例类,我可以创建一个对象,然后在匿名类中打包添加额外的方法。使用单例方法,我可以创建一个对象,然后逐个添加方法:
ob2 = Object.new
def ob2.blather( aStr ) # <= this is a singleton method
puts( "grippity, grippity #{aStr}" )
end
ob2.blather( "ping!" ) #=> grippity, grippity ping!
同样地,我可以重写 “star prize” 程序。在之前的版本中一个名为 starprize
的对象添加了一个单例方法,congratulate
。我也可以很容易地创建一个包含 congratulate
方法的单例类:
starprize = MyClass.new( "Star Prize" )
class << starprize
def congratulate
puts( "You've won a fabulous holiday in Grimsby!" )
end
end
事实上,相似性不仅限于表面。上面代码的最终结果是 congratulate 成为 starprize
的单例方法,并且我已经使用此测试进行了验证:
if item.singleton_methods.include?("congratulate")
单例方法,单例类 - 有什么区别?
简单的说:区别不大。这两种语法提供了向特定对象添加方法,而不是将这些方法构建到其定义类中的不同实现方式。