Thiết lập kế thừa
Thuộc phần Lập trình hướng đối tượng trong hành trình Lua của Coddy. Bài học 31 trên 70.
Đến đây, bạn đã xây dựng các lớp mà mỗi đối tượng tra cứu phương thức trong một bảng prototype duy nhất. Nhưng nếu bạn muốn một lớp kế thừa từ lớp khác thì sao? Đây là lúc tính kế thừa (inheritance) phát huy tác dụng: lớp con có thể truy cập mọi thứ từ lớp cha, đồng thời bổ sung các tính năng riêng.
Điểm mấu chốt là bản thân bảng lớp có thể có metatable. Khi Lua không tìm thấy thứ gì đó trong lớp con, Lua sẽ tìm trong __index của metatable thuộc lớp con, nơi trỏ đến lớp cha.
-- Lớp cha
local Animal = {}
Animal.__index = Animal
function Animal:new()
local obj = {}
setmetatable(obj, Animal)
return obj
end
function Animal:breathe()
print("Breathing...")
endGiờ ta thiết lập kế thừa. Ta tạo một lớp con và đặt metatable của nó để tra cứu lớp cha:
-- Lớp con
local Dog = {}
Dog.__index = Dog
setmetatable(Dog, {__index = Animal})Dòng đơn này, setmetatable(Dog, {__index = Animal}), tạo liên kết kế thừa. Khi một đối tượng Dog gọi phương thức không có trong Dog, Lua sẽ kiểm tra Animal.
Chuỗi tra cứu hoạt động như sau: instance → Dog → Animal. Mỗi bước dùng __index để tìm bảng tiếp theo cần tìm kiếm. Nhờ vậy, các lớp con tự động kế thừa mọi phương thức của lớp cha mà không cần sao chép chúng.
Thử thách
DễHãy xây dựng hệ thống phân cấp kế thừa đầu tiên của bạn! Bạn sẽ tạo mối quan hệ lớp cha con đơn giản, trong đó lớp Machine đóng vai trò là lớp cơ sở, còn lớp Robot kế thừa từ lớp này.
Bạn sẽ sắp xếp code trong ba tệp:
Machine.lua: Định nghĩa lớp cha theo mẫu lớp tiêu chuẩn. Thêm hàm khởi tạo:new()và phương thức:status()để in raMachine is operational. Đừng quên thiết lập__indexvà trả về lớp ở cuối tệp.Robot.lua: Định nghĩa lớp con kế thừa từ Machine. Yêu cầu module Machine, thiết lập bảng Robot với__indexriêng, rồi tạo liên kết kế thừa bằngsetmetatable(Robot, {__index = Machine}). Thêm hàm khởi tạo:new()để tạo một instance có Robot làm metatable.main.lua: Kết hợp mọi thứ bằng cách yêu cầu module Robot, tạo một instance Robot và gọi phương thức:status()được kế thừa.
Điểm cốt lõi ở đây là lớp Robot không tự định nghĩa :status(). Lớp này kế thừa phương thức đó từ Machine thông qua chuỗi metatable. Khi bạn gọi :status() trên một instance Robot, Lua sẽ tìm trong Robot trước. Nếu không tìm thấy, Lua sẽ theo liên kết __index đến Machine, nơi phương thức này được tìm thấy.
Đầu ra của bạn sẽ là:
Machine is operationalDòng duy nhất này chứng minh rằng tính kế thừa đang hoạt động. Robot đã truy cập thành công một phương thức chỉ được định nghĩa trong lớp cha!
Tự làm thử
-- main.lua: Kết nối mọi thứ lại với nhau
-- TODO: Dùng require để nạp module Robot
-- TODO: Tạo một instance Robot bằng Robot:new()
-- TODO: Gọi phương thức (method) :status() được kế thừa trên instance robot của bạn
-- Lệnh này sẽ in ra "Machine is operational"
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
1Khái niệm “self”
Bảng với hàm“self” tường minhCú pháp dấu hai chấmDấu chấm và dấu hai chấmÔn tập: Điểm chuyển động4Dự án: Ngân hàng số
Thiết lập dự ánPhương thức nạp tiền2Mẫu Prototype cho lớp
Khái niệm PrototypeLiên kết bằng __indexHàm khởi tạo :new()Khởi tạo thuộc tínhCác instance độc lậpÔn tập: Nhà máy ô tô5Nạp chồng toán tử trong OOP
Cộng các đối tượngTrừ các đối tượngNối các đối tượngSo sánh các đối tượng (<, >)Ôn tập: phép tính với ví tiền8Đóng gói
Quy ước đặt tênClosure để bảo mậtTruy cập qua closureBảng chỉ đọcLogic kiểm tra hợp lệTổng kết: Két an toàn11Mẫu thiết kế (cơ bản)
Hàm tạo đối tượngBảng SingletonMẫu IteratorObserver (Listener)Ôn tập: Factory Logger3Trạng thái và hành vi của đối tượng
Biến instancePhương thức getterPhương thức setterThuộc tính tính toánĐịnh dạng chuỗiKiểm tra tính bằng nhauÔn tập: điểm số học sinh6Cơ bản về kế thừa
Thiết lập kế thừaKế thừa phương thứcMở rộng hàm khởi tạoThêm phương thức cho lớp conDùng chung và riêngÔn tập: hệ phân cấp hình dạngTự luyện tập: Trình biên dịch Lua online