Gọi super
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 24 trên 57.
Bên trong một phương thức ghi đè, super gọi phiên bản của cùng phương thức trong lớp cha. Lớp con có thể dựa trên kết quả đó thay vì lặp lại:
class Greeter
def greet(name)
"Hello, #{name}"
end
end
class LoudGreeter < Greeter
def greet(name)
super.upcase + "!"
end
end
puts LoudGreeter.new.greet("Ada")Đầu ra:
HELLO, ADA!Cách dùng phổ biến nhất là initialize: lớp con nhận thêm một giá trị, truyền các giá trị chung cho lớp cha bằng super(...) rồi lưu giá trị riêng:
class Person
attr_reader :name, :age
def initialize(name, age)
@name = name
@age = age
end
end
class Student < Person
attr_reader :school
def initialize(name, age, school)
super(name, age)
@school = school
end
end
s = Student.new("Ada", 20, "MIT")
puts "#{s.name}, #{s.age}, #{s.school}"Đầu ra:
Ada, 20, MITBa dạng này khác nhau ở các đối số được truyền. super không có ngoặc truyền các đối số mà phương thức hiện tại đã nhận; super() không truyền đối số nào; super(a, b) chỉ truyền đúng các đối số đó:
class Base
def show(*args)
"Base got #{args.inspect}"
end
end
class Child < Base
def show(a, b)
[super, super(), super(b)].join(" | ")
end
end
puts Child.new.show(1, 2)Đầu ra:
Base got [1, 2] | Base got [] | Base got [2]super có thể chạy ở bất cứ đâu trong phương thức hoặc chỉ khi thỏa mãn một điều kiện. Khi initialize của lớp con nhận các đối số khác với initialize của lớp cha, super không kèm đối số sẽ truyền sai đối số, đây là nguyên nhân phổ biến gây ra ArgumentError:
class Logger
def log(message)
puts "LOG #{message}"
end
end
class QuietLogger < Logger
def log(message)
super unless message.start_with?("debug")
end
end
logger = QuietLogger.new
logger.log("started")
logger.log("debug x=1")
logger.log("done")Đầu ra:
LOG started
LOG doneThử thách
DễHoàn thiện các lớp. Person lưu name và age, còn to_s trả về Ada (36). Student bổ sung trường học: initialize truyền tên và tuổi cho super, còn to_s trả về Ada (20), studies at MIT, được tạo từ super. Teacher bổ sung môn học theo cách tương tự và trả về Bo (45), teaches maths.
Code được cung cấp đọc các dòng person Ada 36, student Ada 20 MIT hoặc teacher Bo 45 maths rồi in ra từng đối tượng.
Code của bạn nằm trong person.rb, student.rb và teacher.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 'person'
require_relative 'student'
require_relative 'teacher'
# Đ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, age, extra = line.split
person = case kind
when "student" then Student.new(name, age.to_i, extra)
when "teacher" then Teacher.new(name, age.to_i, extra)
else Person.new(name, age.to_i)
end
puts person
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ệTự luyện tập: Trình biên dịch Ruby online