Mở rộng đối tượng
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 28 trên 57.
extend thêm các phương thức của một module vào một đối tượng thay vì thêm vào tất cả các instance. Khi mở rộng một lớp, các phương thức được thêm vào đối tượng lớp, vì vậy chúng trở thành phương thức của lớp:
module Describable
def describe
"#{name} has #{instance_methods(false).size} methods"
end
end
class Dog
extend Describable
def bark
"Woof"
end
def sit
"sits"
end
end
puts Dog.describeĐầu ra:
Dog has 2 methodsMột module được dùng với extend có thể lưu trạng thái trong các biến instance của lớp. Mỗi lớp kế thừa module đó sẽ có một bản sao riêng, dưới dạng biến instance của lớp:
module Counted
def created
@created ||= 0
end
def record
@created = created + 1
end
end
class Order
extend Counted
end
class Invoice
extend Counted
end
Order.record
Order.record
Invoice.record
puts "#{Order.created} #{Invoice.created}"Đầu ra:
2 1extend cũng hoạt động với một đối tượng đơn lẻ. Chỉ đối tượng đó có thêm các phương thức; các instance khác thuộc lớp đó vẫn không thay đổi, và is_a? trả về true chỉ với đối tượng được mở rộng:
module Shiny
def polish
"#{self} is shining"
end
end
a = "car"
b = "bike"
a.extend(Shiny)
puts a.polish
puts a.is_a?(Shiny)
puts b.respond_to?(:polish)Đầu ra:
car is shining
true
falseHai từ khóa này đặt các phương thức của cùng một module vào những nơi khác nhau. include biến chúng thành phương thức instance của một lớp, còn extend biến chúng thành phương thức của chính đối tượng được mở rộng:
class Order
include Printable # order.print_me (mọi instance)
extend Counted # Order.record (chính lớp đó)
end
item.extend(Shiny) # item.polish (chỉ đối tượng này)Thử thách
DễHoàn thiện module Registry, các lớp sử dụng module này với extend. register(name) thêm một tên vào danh sách riêng của lớp, lưu trong @entries (được tạo khi dùng lần đầu), và trả về Plugin registered x; nếu tên đã có trong danh sách, hàm trả về Plugin already has x. entries trả về danh sách, còn count trả về kích thước của danh sách. Cả Plugin và Theme đều mở rộng Registry và giữ danh sách riêng.
Code được cung cấp đọc các dòng plugin name hoặc theme name, gọi register trên lớp tương ứng và in câu trả lời. Cuối cùng, chương trình in plugins: a, b (2) và themes: ..., hoặc none (0) nếu danh sách trống.
Code của bạn nằm trong registry.rb, plugin.rb và theme.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 'registry'
require_relative 'plugin'
require_relative 'theme'
# Đoạn code đầu vào/đầu ra có sẵn: giữ nguyên
input = []
while (line = gets)
input << line.chomp
end
input.each do |line|
kind, name = line.split
target = kind == "plugin" ? Plugin : Theme
puts target.register(name)
end
[["plugins", Plugin], ["themes", Theme]].each do |label, klass|
list = klass.entries.empty? ? "none" : klass.entries.join(", ")
puts "#{label}: #{list} (#{klass.count})"
end
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
1Lớp và đối tượng
Làm việc với tệpĐịnh nghĩa lớpBiến instancePhương thức và selfto_s và inspectÔn tập: thẻ thư viện4Tính đóng gói
Phương thức riêng tưPhương thức được bảo vệPhương thức thiết lập riêng tưBảo vệ trạng tháiÔn tập: máy bán hàng tự động7Tính đa hình và duck typing
Tính đa hìnhDuck typingPhương thức trừu tượngcase và lớpÔn tập: phương thức thanh toán2Phương thức truy cập và self
Phương thức đọc và ghiPhương thức gán tùy chỉnhself trong phương thứcĐịnh danh và tính bằng nhauÔn tập: Danh sách liên hệ3Phương thức và biến của lớp
Phương thức lớpBiến thực thể của lớpHằng sốPhương thức tạo đối tượngÔn tập: mã giảm giá6Module và mixin
Module và includeMở rộng đối tượngModule ComparableModule EnumerableÔn tập: giải đấu thể thaoTự luyện tập: Trình biên dịch Ruby online