真的骄傲梦想家园
专业源于兴趣和努力

类变量和类方法
一直以来,我们创建的所有类都包含有实例变量和实例方法:与某个具体的类实例相关联的变量和方法。
有时候,类也需要有自己的状态。于是就有了类变量。
类变量
类变量在类的所有对象中共享,也能被我们后面介绍的类方法访问。一个具体的类变量在给定的类中只有一个拷贝。
类变量名由两个"at"符号开始,如@@count。与全局变量和实例变量不同,类变量在使用前必须先初始化。
通常,初始化只是在类内定义一个简单的赋值。
例如,我们的自动唱机想记录每首歌的播放次数。当播放歌曲的时候,在实例中的这个值会增加。
但我们还想知道总共有多少歌已经播放了。我们可以通过查找所有的Song实例并把它们的计数相加或
冒着脱离良好设计的风险使用一个全局变量来做到。相反,我们使用一个类变量。

Code

为了调试的需要,我特意在Song#play时返回一个包含了这首歌播放次数的字符串和所有歌的播放总次数。
我们简单地测试一下。

Code


类变量对于类和它的实例是私有的。如果你想使它们能被外面访问,你将需要编写一个访问器方法。
这个方法可以是一个实例方法,也可以是下面我们将要提到的类方法。

类方法
有时候类需要提供一些不与特定实例绑定的方法。我们已经使用过一个这样的方法了。
这个new方法创建一个新的Song对象,但它不与具体的song相关联。

song = Song.new(.)

 


你Ruby类库中你都能找到类方法的影子。例如,File类的对象对应一个文件系统下打开的文件。
然而,File类还提供了许多类对象来操作没有打开的文件,所以没有File对象。
如你想删除一个文件,你调用类文件File.delete,传入文件名。

File.delete("doomed.txt")

 


类文件通过定义来与实例方法区分;类方法的名字定义为在方法名字前加上类名和点。

Code

自动唱机是按歌来计费而不是按时间。这使用短的歌曲比较长的歌曲利润高。我们想防止在播放列表中的歌曲太长。
我们可以在播放列表中定义一个类方法来检查一个具体的歌曲是否超出范围。我们通过一个类常量来设定这个范围,
这是一个简单的常量(还记得常量吗?它们用大写字母开头)它在类内初始化。

Code

 

单例模式和其它结构
有时候你想重写Ruby创建对象的默认方式。例如,我们的自动唱机。因为我们有许多自动唱机分布在整个国家,
我们想要尽可能简单地维护它们。其中一个要求是记录自动唱机发生的所有事情:歌曲播放,收到付款,
奇怪的数据流等等。因为我们想保留音乐的网络带宽,所以我们会把这些记录文件保存在本地。
也就是说,我们需要一个类来处理这些记录。然而,我们想要每个自动唱机只有一个记录对象,
我们还希望这个记录对象能被其它对象使用。这就是单例模式。我们整理了这些事情,因此创建记录对象的唯一方式
是调用MyLogger.create,我们将确保永远只有一个记录对象被创建。

Code


通过使MyLogger的new方法变为私有,我们阻止并使用这个的构造函数创建记录对象。
取代的是,我们提供了一个类方法MyLogger.create。这个方法使用类变量@@logger保存
logger单一实例的引用,每次调用这个方法时都返回这个实例。
我们通过查看这个方法返回的标识符来测试它。

Code

 

使用类方法作为伪构造函数能使你的类的用户更加容易使用。例如,一个描述多边形的Shape类。
Shape的实例使用给定的构造函数创建,它需要边数和周长两个参数。

Code


然而,几年过去后,这个类被用在了不同的应用程序中,这个程序通过名字和一边的长度来创建图形,而不是周长。
简单地给Shape添加一些类方法。

Code


类方法有许多有趣的强大的应用,但发掘他们并不会让我们的自动唱机更早地完成,所以让我们继续吧。

posted on 2008-12-05 20:15  真的骄傲  阅读(1676)  评论(0编辑  收藏  举报