Phương thức tạo đố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 15 trên 57.
Phương thức tạo đối tượng (factory method) là một phương thức của lớp, tạo và trả về một instance. Nó đặt tên cho một cách tạo đối tượng. Bên trong phương thức của lớp, new có nghĩa là self.new:
class Temperature
attr_reader :celsius
def initialize(celsius)
@celsius = celsius
end
def self.from_fahrenheit(f)
new((f - 32) * 5 / 9.0)
end
def self.freezing
new(0)
end
end
puts Temperature.from_fahrenheit(212).celsius
puts Temperature.freezing.celsiusĐầu ra:
100.0
0Chuyển văn bản thành đối tượng là công việc phổ biến của một lớp nhà máy. Phần phân tích nằm cạnh lớp, còn initialize vẫn đơn giản:
class Duration
attr_reader :seconds
def initialize(seconds)
@seconds = seconds
end
def self.parse(text)
new(text.split(":").map(&:to_i).reduce(0) { |acc, part| acc * 60 + part })
end
end
puts Duration.parse("1:30").seconds
puts Duration.parse("2:00:05").secondsĐầu ra:
90
7205Một factory có thể từ chối đầu vào không hợp lệ. Trả về nil cho phép bên gọi kiểm tra kết quả bằng if; phát sinh lỗi sẽ dừng chương trình trừ khi bên gọi bắt lỗi:
class Color
attr_reader :hex
def initialize(hex)
@hex = hex
end
def self.parse(text)
return nil unless text.match?(/\A#[0-9a-f]{6}\z/i)
new(text.downcase)
end
end
["#FF8800", "orange"].each do |text|
color = Color.parse(text)
puts color ? "ok #{color.hex}" : "not a color: #{text}"
endĐầu ra:
ok #ff8800
not a color: orangeprivate_class_method :new khiến bạn chỉ có thể gọi new bên trong lớp, vì vậy các hàm tạo trở thành cách duy nhất để tạo đối tượng:
class Money
attr_reader :cents
def initialize(cents)
@cents = cents
end
private_class_method :new
def self.from_cents(cents)
new(cents)
end
end
puts Money.from_cents(250).cents
begin
Money.new(250)
rescue NoMethodError => e
puts e.message
endĐầu ra:
250
private method `new' called for class MoneyThử thách
DễHoàn thiện lớp Duration. initialize(seconds) lưu số giây. Hàm tạo Duration.parse(text) đọc định dạng m:ss hoặc h:mm:ss, hàm tạo Duration.from_minutes(m) nhận số phút nguyên, plus(other) trả về một Duration mới có tổng thời lượng, còn to_s trả về định dạng h:mm:ss với phút và giây gồm hai chữ số.
Code được cung cấp đọc các khoảng thời lượng: những dòng như 45m được xử lý bằng from_minutes, các dòng còn lại được xử lý bằng parse. Code in ra từng khoảng thời lượng, rồi in ra total 1:47:10.
Hãy viết code trong duration.rb. main.rb chứa code đầu vào/đầu ra được cung cấp và không thể chỉnh sửa.
Tự làm thử
require_relative 'duration'
# Đoạn code đầu vào/đầu ra có sẵn: giữ nguyên
input = []
while (line = gets)
input << line.chomp
end
durations = input.map do |line|
line.end_with?("m") ? Duration.from_minutes(line.to_i) : Duration.parse(line)
end
durations.each { |d| puts d }
puts "total #{durations.reduce(Duration.new(0)) { |sum, d| sum.plus(d) }}"
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áTự luyện tập: Trình biên dịch Ruby online