Ghi đè phương thức
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 37 trên 70.
Cho đến nay, các lớp con đã kế thừa phương thức của lớp cha và thêm phương thức mới. Nhưng nếu lớp con cần cùng tên phương thức nhưng có hành vi khác thì sao? Đây gọi là ghi đè phương thức (method overriding).
Khi bạn định nghĩa một phương thức trong lớp con có cùng tên với phương thức trong lớp cha, phiên bản của lớp con sẽ được ưu tiên. Chuỗi tra cứu của Lua kiểm tra lớp con trước. Nếu tìm thấy phương thức ở đó, chuỗi sẽ dừng tìm kiếm.
local Animal = {}
Animal.__index = Animal
function Animal:new(name)
local obj = {name = name}
setmetatable(obj, Animal)
return obj
end
function Animal:speak()
print(self.name .. " makes a sound")
end
-- Dog ghi đè phương thức speak()
local Dog = {}
Dog.__index = Dog
setmetatable(Dog, {__index = Animal})
function Dog:new(name)
local obj = Animal.new(Animal, name)
setmetatable(obj, Dog)
return obj
end
function Dog:speak()
print(self.name .. " barks: Woof!")
endGiờ đây, mỗi lớp phản hồi khác nhau với cùng một lời gọi phương thức:
local generic = Animal:new("Creature")
local buddy = Dog:new("Buddy")
generic:speak() -- Đầu ra: Creature phát ra tiếng kêu
buddy:speak() -- Đầu ra: Buddy sủa: Woof!Phiên bản :speak() của Dog thay thế hoàn toàn phiên bản của lớp cha trong các đối tượng Dog. Nhờ đó, bạn có thể tạo hành vi chuyên biệt mà vẫn giữ giao diện nhất quán: mọi loài động vật đều có thể :speak(), nhưng mỗi loài thực hiện theo cách khác nhau.
Thử thách
DễHãy xây dựng một vương quốc động vật nhỏ, nơi các loài vật khác nhau phát ra tiếng kêu riêng! Bạn sẽ tạo lớp cha Animal và hai lớp con, Cat và Cow. Mỗi lớp con sẽ ghi đè phương thức :speak() của lớp cha bằng cách hoạt động riêng.
Bạn sẽ sắp xếp code trong bốn tệp:
Animal.lua: Lớp cơ sở với hàm khởi tạo:new(name)để lưu tên con vật. Thêm phương thức:speak()để in tên con vật, theo sau làmakes a sound. Đây là cách hoạt động mặc định mà các lớp con sẽ ghi đè.Cat.lua: Lớp con kế thừa từ Animal. Hàm khởi tạo:new(name)cần gọi hàm khởi tạo của lớp cha, sau đó liên kết lại metatable với Cat. Ghi đè phương thức:speak()để mèo phát ra tiếng khác: in tên con mèo, theo sau làmeows: Meow!Cow.lua: Một lớp con khác kế thừa từ Animal. Thiết lập hàm khởi tạo giống như Cat. Ghi đè:speak()để bò in tên của mình, theo sau làmoos: Moo!main.lua: Kết hợp mọi thứ! Đọc hai tên từ đầu vào, tạo Cat với tên thứ nhất và Cow với tên thứ hai, sau đó gọi:speak()cho từng con để cho thấy cùng một tên phương thức tạo ra đầu ra khác nhau tùy theo lớp.
Bạn sẽ nhận được hai đầu vào:
- Tên con mèo
- Tên con bò
Trong tệp chính, hãy tạo cả hai con vật và gọi :speak() cho mèo trước, sau đó cho bò.
Ví dụ, nếu đầu vào là Whiskers và Bessie, đầu ra sẽ là:
Whiskers meows: Meow!
Bessie moos: Moo!Hãy chú ý cách cả hai con vật đều phản hồi cùng một lần gọi phương thức :speak(), nhưng mỗi con tạo ra đầu ra riêng theo kiểu của mình. Phiên bản của Cat thay thế hoàn toàn cách hoạt động chung chung của lớp cha, makes a sound, và Cow cũng vậy. Đây là cách ghi đè phương thức hoạt động: cùng giao diện, cách triển khai khác nhau!
Tự làm thử
-- main.lua: Kết hợp mọi thứ lại
local Cat = require('Cat')
local Cow = require('Cow')
-- Đọc đầu vào
local catName = io.read()
local cowName = io.read()
-- TODO: Tạo một Cat với tên đầu tiên
-- TODO: Tạo một Cow với tên thứ hai
-- TODO: Gọi :speak() cho mèo trước, rồi cho bò
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ền7Đa hình và ghi đè
Ghi đè phương thứcGọi phương thức của lớp chaGõ kiểu vịtGiao diện chungKiểm tra kiểuÔn tập: Vai trò của nhân viê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