前情提要:
在第四天里,我们用参赛者的例子解说实体方法与类别方法。
类别中的实体物件,想要玩弄方法时,可以有三种取用方式:(跟斯斯有三种一样)
该类别所定义的实体方法。
模块中可取得的实体方法。(关于模块,记得第三天的include与extend比较吗?)
类别方法:类别物件的singleton method
Class can use methods from three areas:
Instances of class can call methods that are defined as instance methods in their class.
Instances of Class have access to the instance methods defined in Module
Or instances can call a singleton method of a class object.出处
所以我们在今天要解说一下self与singleton method啰!
Ruby经典面试题目#05
self是什么意思?What does self mean?
self有丰富层次的含义。就跟我们的内心一样(??来点播一首陈绮贞的Self??)它虽然代表自己本身的物件Object,但还记得,我们在第一天说到,Ruby的世界几乎都是物件吗?
因此,self有两种意思:
Self在类别class里,代表目前的类别(leafor)。
Self在实体instance里,代表目前的实体。
简单解释:实体就是物体在內存的位置,就好像每个宝宝(实体)生下来,都是从某个妈妈的子宫(內存)里出来的。我们必须经历过实体化的过程才能成为一个活生生的人呢!
幸好,产生一个实体不用等“怀胎十月”这么久,只要像我们在第一天一样使用@宣告內存位置就可以产生实体变数了:
class LoveSong
def initialize
@message =“I was born to love you!”#定义实体变数(instance variable)@message
end
def sing_a_song
puts @message
end
end
Ting = LoveSong.new
Ting.sing_a_song
#=> I was born to love you!
用LoveSong类别另写一段代码实作self:
class LoveSong
def
self.song1()
“We are the champions!”
end
class << self
def song2()
“We will rock you!”
end
end
p self # => LoveSong
p self.class # => Class
p self.singleton_methods # [:song1,:song2]
p self.song1()#=>“We are the champions!”
p self.song2()#=>“We will rock you”
end
在这里的self代表目前的类别名称LoveSong,我们查询self.class还是类别class,而这里的self.singleton_method出现了:song1与:song2这两个能够分别印出两首歌的类别方法(class method)。
我们在第一天文章曾经提到利用superclass查找父类别的方法,查到类别的父类别,是物件。class.superclass是object。
但其实:每一个类别class上面都还有一层隐形的类别class(隐形的翅膀),我们可以称作metaclass超类别。
在Ruby,类别class上面的隐形类别,我们叫它eigenclass特征类别。出处]。
Singleton Method
单例方法=单例类别的实体方法。
(指的是某物件实体「的单例类别」的实体方法,而不仅是某个物件的实体方法,中间多夹了一层隐形的翅膀「单例类别」)
singleton methods of an object are not instance methods of the class of the object;
they are instance methods of the singleton class of the object.
当我们讲到Singleton Method,就会提到Singleton Pattern单例模式,这个在面向对象语言(如:Java)共同的观念。
如果我们能保证某一个类别只产生一个物件实体,而且提供存取该物件的统一方法。这种设计模式就称为单例模式。
我们可以直接存取,而不需要实体化此类别的物件。
使用Singleton Method的时机
当我们想控制实体数目,节省系统资源的时候。
再度把例子搬出来:一间教室里只有一台打印机,所有电脑都可以联机打印机,但打印机一次只能印出一台电脑上的文件。
还记得我们在第四天举的例子是查找铁人参赛者名单吗?在这个例子中,一次只能查找一名参赛数据。
class IronmanList
def self.find(id)
p“finding Ironman ID: #{id}”
end
end
IronmanList.find(1)
使用规则:
此类别只能有一个物件实体。(IronmanList类别中,只有一个self)
此类别必须自己建立自己的唯一实体:def self.find(id)
此类别必须给其他物件提供这个实体。
使用场景:
此物件是类别中唯一的物件。如同IronmanList的序列号唯一。(跟身份证号码一样)
当创建此物件需要消耗较的资源过多时,可节省系统资源。(例如:连接数据库、连接打印机)
当我们为实体定义了自已的singleton method,代表了这个方法只属于该实体,尽管是相同的class的实体也无法使用别人的singleton method。(每个实体的单例类别是不同的。)
总结
近一步说明类别方法、实体方法,与单例方法的关系。中文翻译的话,我们可以这样记:
类别的eigenclass(特征类别)方法=类别方法(xcsjbj)。
实体的eigenclass(特征类别)方法=单例方法=单例类别的实体方法。
实体方法
实体已在类别里定义好了。
如果你需要将实体方法,运用在某个特定的实体,就记得要在类别里定义好这个实体。
举例:“每个人(物件实体)都能赢得”的方法
类别方法
类别方法并不在类别里定义,而是在类别里的物件实体的一种单例方法。
如果此方法并不会和某个特定的实体变数绑在一起,就使用类别方法!
举例:“查找名单”的方法
学程序的好处就是会查找许多原文数据(间接提升英文阅读功力!)
进一步发现许多原则上的定义用英文表达会更为清楚。
所以,我们第四天(实体方法与类别方法)与第五天的总结(单例方法的进一步说明),从这段英文就能看得更加清楚之间的关系了:)
Instance methods are methods of a class(defined in the class's definition)
Class methods are singleton methods on the Class instance of a class(not defined in the class's definition).They are defined on the singleton class of the object.More Information
编按:这篇算是我目前为止写过最有挑战性的IT文章,因为牵涉到metaprogramming的定义,从一开始自己一头雾水的情况,努力查找许多原文数据,也从自己撰写代码举例之后,总算获得一点头绪。(还记得第一版写完的时候,自己也看不懂在写什么XD,多读几遍+反复润饰之后才渐渐领悟开窍。)写文章或技术笔记的好处就是要真的懂了才写得出来。若新手小妹我翻译或理解上有错误,还请板上资深网友多多指教!:)