模块与 include
本课属于 Coddy Ruby 学习旅程的“面向对象编程”单元。第 27 课,共 57 课。
模块是一组有名称的方法。它不能创建对象,但类可以include它,这样每个实例就都拥有该模块的方法,就像这些方法是由类定义的一样。这称为混入:
module Greetable
def greet
"Hello, I am #{name}"
end
end
class Person
include Greetable
attr_reader :name
def initialize(name)
@name = name
end
end
puts Person.new("Ada").greet输出:
Hello, I am Ada模块的方法可以调用类提供的方法,例如上面的 name。因此,只要每个类都提供模块所使用的方法,一个模块就可以服务于各种不同的类:
module Greetable
def greet
"Hello, I am #{name}"
end
end
class Robot
include Greetable
def name
"R2"
end
end
class City
include Greetable
def name
"Paris"
end
end
puts Robot.new.greet
puts City.new.greet输出:
Hello, I am R2
Hello, I am Paris一个类只有一个父类,但可以包含任意数量的模块。include? 用来检查一个类是否包含某个模块,该模块会出现在 ancestors 中,紧跟在类之后。Ruby 会按这个顺序查找方法:
module Swimmer
def swim
"swimming"
end
end
module Flyer
def fly
"flying"
end
end
class Duck
include Swimmer
include Flyer
end
d = Duck.new
puts "#{d.swim}, #{d.fly}"
puts Duck.include?(Flyer)
p Duck.ancestors.take(3)输出:
swimming, flying
true
[Duck, Flyer, Swimmer]模块还会将相关的类和常量归到同一个名称下,也就是一个命名空间,这样名称就不会冲突。Shop::Item 和 Game::Item 是不同的类:
module Shop
TAX = 0.2
class Item
def label
"shop item, tax #{TAX}"
end
end
end
puts Shop::Item.new.label
puts Shop::TAX输出:
shop item, tax 0.2
0.2挑战
简单完成这些模块和类。Greetable#greet 使用对象的 name,并返回 Hello, I am Ada。Walkable#walk(steps) 会把步数加到存储在 @steps 中的计数器上(第一次从 nil 开始),并返回 Ada walked 30 steps,也就是累计步数。Person 包含这两个模块;Robot 只包含 Greetable,它的名称由 R- 和序列号组成。
提供的代码会根据第一行(Ada 7)创建一个人和一个机器人,然后运行 greet p、greet r 或 walk 10(针对这个人)这些命令,并打印每条命令的结果,最后输出 robot walks: false。
你的代码要写在 greetable.rb、walkable.rb、person.rb 和 robot.rb 中。main.rb 包含提供的输入/输出代码,不能编辑。
亲手试试
require_relative 'greetable'
require_relative 'walkable'
require_relative 'person'
require_relative 'robot'
# 提供的输入输出代码:保持原样
input = []
while (line = gets)
input << line.chomp
end
name, serial = input[0].split
person = Person.new(name)
robot = Robot.new(serial)
input.drop(1).each do |line|
command, arg = line.split
if command == "walk"
puts person.walk(arg.to_i)
else
target = arg == "p" ? person : robot
puts target.greet
end
end
puts "robot walks: #{Robot.include?(Walkable)}"
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Ruby 在线编译器