对象与方法
先教大家一句咒语: Ruby中,一切皆对象。
对象(Object)
Ruby是一门解释执行的动态语言,同时,它也是一门完完全全的面向对象语言。
对象,很好理解,它表示客观世界中某个具体的个体事物,它是面向对象世界中的基本单元。它是某一个类的具体实例, 一个对象,应该包含其唯一的标识符,属性(attributes)以及方法(Methods)。
属性(attributes)即为一个对象的特点,用于描述这个对象的个性,而方法(Methods),则为这个对象能够提供的服务,及其行为。
举个例子:
人类,是一个类别。 人类中某个个体,为张三。 他是男性,中国人,黄色人种。他会做饭,是大厨,他唱歌也很好听。
那么用Ruby代码来描述的话,应该是这样的:
# 人类
Class People
attr_accessor :name, :gender, :race, :nationality
def initialize(name='', gender='', race='', nationality='')
@name = name
@gender = gender
@race = race
@nationality = nationality
end
end
# 上帝造了张三
person = People.new
person.name = "张三"
person.gender = '男'
person.race = 'yellow'
person.nationality = 'China'
def person.chef
puts "good"
end
def person.sing
puts "good"
end
上面的代码, Class即为创建一个类,比如People, 是指人类。
attr_accessor , 声明了People类的属性,比如,人类是有名字(name)、有性别(gender)、有种族(race)、有国籍(nationality)。
我们可以使用new方法,来使用People类来造一个对象,也就是一个人, 我们用person表示。
person = People.new
我们使用「点」来指定person的name,并赋与其值。
person.name = '张三'
而实际上,attr_accessor,是动态生成了类似下面的方法:
class People
# ...
def name
@name
end
def name=(name)
@name=name
end
# 其他属性方法类似
end
def,是声明一个方法, 为对象创建一个行为。 比如上面的person.name = '张三', 就是允许给person起名字。
而像下面这样的代码:
def person.chef
puts "good"
end
当执行person.chef的时候,会输出‘good’。
则是给「张三」这个个体创建一个头衔,厨师(chef),代表他会做饭。这个会做饭的技能, 只是他这一个个体特有的,你可以再创建一个人「李四」来尝试一下:
other_person = People.new
other_person.name = '李四'
你可以让「李四」来调用chef方法, 则会报错。
消息传递
我们上面的代码中: person.chef , 我们叫它方法调用。
而Ruby更愿意把它称作,消息传递。
person,是一个对象, 是一个消息接收者。
chef,是一个消息。
通过一个「点」, 我们把chef这个消息传递给person, 假如person可以响应这个消息,那么它就会响应结果,否则,则报错无法响应。
消息传递,是对象之间传递信息的唯一手段。
还记得我们的咒语吗? Ruby中一切皆对象。我们使用Ruby,就是使用对象, 想让对象为你工作,那么你就得给他传递消息。
包括要设置对象自己的属性,也是使用消息传递的方式,这也是上面代码中为什么要有「attr_accessor」方法。
另一句咒语: Ruby中一切都是消息传递(「方法调用」)
所以,Ruby里各种内建数据结构,比如字符串、数组、Hash等,也内置了一些方法,你也可以用同样的方式来调用。可以去ruby-doc.org来查找这些方法。
Chef中的抽象
回头看我们的自动化管理工具Chef中的一些概念,我们更容易理解这种对象与消息的思想。
比如,在OpsCode给出的apache Cookbook中,设置attributes的一段代码:
node.default["apache"]["dir"] = "/etc/apache2"
node.default["apache"]["listen_ports"] = [ "80","443" ]
node, 即为一个对象,Chef中把具体要配置管理的服务器,抽象为一个类Node,而上面代码中的node,即为那个具体的要使用Chef进行配置管理的服务器或者是其他Chef可配置管理的任何东西。
思考:
结合本节的内容,来思考下面这段代码的意思?
node.default['apache']['dir'] = '/etc/apache2'