Menu
CoddyTech

Module và include

Thuộc phần Lập trình hướng đối tượng trong hành trình Ruby của Coddy. Bài học 27 trên 57.

module là một nhóm có tên gồm các phương thức. Nó không thể tạo đối tượng, nhưng một lớp có thể include module đó, rồi mọi instance đều có các phương thức của module như thể lớp đã định nghĩa chúng. Đây gọi là mixin:

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

Đầu ra:

Hello, I am Ada

Các phương thức của module có thể gọi những phương thức mà lớp cung cấp, chẳng hạn như name ở trên. Vì vậy, một module có thể dùng cho nhiều lớp rất khác nhau, miễn là mỗi lớp cung cấp những gì module sử dụng:

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

Đầu ra:

Hello, I am R2
Hello, I am Paris

Một lớp chỉ có một lớp cha, nhưng có thể bao gồm bất kỳ số lượng module nào. include? kiểm tra xem một lớp có bao gồm một module hay không. Module đó xuất hiện trong ancestors, ngay sau lớp, đây là nơi Ruby tìm các phương thức của lớp:

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)

Đầu ra:

swimming, flying
true
[Duck, Flyer, Swimmer]

Module cũng nhóm các lớp và hằng số liên quan dưới một tên gọi, gọi là namespace, để các tên không bị trùng lặp. Shop::Item và Game::Item là hai lớp khác nhau:

module Shop
  TAX = 0.2

  class Item
    def label
      "shop item, tax #{TAX}"
    end
  end
end

puts Shop::Item.new.label
puts Shop::TAX

Đầu ra:

shop item, tax 0.2
0.2
challenge icon

Thử thách

Dễ

Hoàn thành các module và lớp. Greetable#greet trả về Hello, I am Ada, sử dụng name của đối tượng. Walkable#walk(steps) cộng số bước vào bộ đếm lưu trong @steps (lần đầu bắt đầu từ nil) và trả về Ada walked 30 steps, tổng số bước tích lũy. Person bao gồm cả hai module; Robot chỉ bao gồm Greetable và tên của nó là R- theo sau bởi một số sê-ri.

Code được cung cấp tạo một người và một robot từ dòng đầu tiên (Ada 7), sau đó chạy các lệnh greet p, greet r hoặc walk 10 (dành cho người đó), in ra từng kết quả, rồi cuối cùng robot walks: false.

Code của bạn đặt trong greetable.rb, walkable.rb, person.rb và robot.rb. main.rb chứa code đầu vào/đầu ra được cung cấp và bạn không thể chỉnh sửa tệp này.

Tự làm thử

require_relative 'greetable'
require_relative 'walkable'
require_relative 'person'
require_relative 'robot'

# Đoạn code đầu vào/đầu ra có sẵn: giữ nguyên
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)}"
quiz iconTự kiểm tra

Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.

Tất cả bài học trong Lập trình hướng đối tượng

Tự luyện tập: Trình biên dịch Ruby online