类的层次结构、属性与变量
在上一节结束时我们创建两个类:Thing 和 Treasure,尽管事实上这两个类共享了一些功能(特别是两者都包含 ‘name’),但它们是没有联系的。
现在,这两个类的重复看起来是不值一提的。但是,当你开始写一些复杂的程序时,你的类将会包含大量的变量和方法;你真的想将同样的事情一遍又一遍的重复吗。
对于其中一个类是其它(祖先)类的特殊类型结构来说创建一个类层次是更有意义的,这种情况下它会自动继承(inherit)祖先类的特征。例如,在我们简单的冒险游戏中,Treasure 是 Thing 的一个特殊的类型,因此 Treasure 就会继承 Thing 类的特征。
Thing 类的特征通常被定义在它内部,Treasure 类则会自动地“继承” Thing 类所有的的特性。所以,我们不需要再次对这些特征进行编码,而是额外添加一些 Treasures 类特有的特性。
通常地规则是,在创建类层次结构时,具有更多通用特征的类要比具有更多特殊特征的类层次更高一些。所以,只有一个 name 和 description 的 Thing 类是具有 name、description 以及 value 的 Treasure 类的祖先;Thing 类也可能是一些其它的特殊类的祖先,例如具有 name、description 以及 exits 的 Room 类。
- 一个父亲,有多个孩子…
-
@name
和@description
)。Treasure 和 Room 类都派生自 Thing 类,所以它们自动地继承了 name 和 description 。Treasure 类添加了一个 value,所以它就具有 name、description 和 value ;Room 类添加了一个 exits,所以它就具有 name、description 和 exits 。
来让我们看看如何在 Ruby 中创建一个后代类。加载 1adventure.rb 程序,这只需要定义一个具有两个实例变量(instance variables)@name
和 @description
的 Thing 类,它们的值可以在创建新的 Thing 对象时在 initialize
方法中赋值。
实例变量通常不能(也不应该)被外部直接访问,这是为了遵循上一章讲到的封装( encapsulation)原则。为了获得我们所需要的每个变量的值,我们需要一个 get 访问器方法,例如 get_name
;为了给某个变量赋一个新值,我们也需要一个 set 访问器方法,例如 set_name
。