Metamethod số học phần 2
Thuộc phần Logic và luồng chương trình trong hành trình Lua của Coddy. Bài học 22 trên 54.
Dựa trên phép cộng và phép trừ, bạn cũng có thể định nghĩa cách các bảng xử lý phép nhân và phép chia bằng các metamethod __mul và __div. Chúng hoạt động giống như __add và __sub, nhưng phản hồi với các toán tử * và /.
Phương thức chuyển tải __mul đặc biệt hữu ích khi bạn muốn thay đổi tỉ lệ các giá trị trong bảng. Ví dụ, nhân một vector với một số (gọi là số vô hướng) sẽ nhân từng thành phần:
local vector = {x = 3, y = 4}
local meta = {
__mul = function(a, b)
local scalar = type(a) == "number" and a or b
local vec = type(a) == "table" and a or b
return {x = vec.x * scalar, y = vec.y * scalar}
end
}
setmetatable(vector, meta)
local scaled = vector * 2
print(scaled.x, scaled.y) -- Đầu ra: 6 8Hãy chú ý cách hàm kiểm tra toán hạng nào là số và toán hạng nào là bảng. Nhờ đó, cả vector * 2 lẫn 2 * vector đều hoạt động chính xác.
Metamethod __div hoạt động tương tự với phép chia:
local meta = {
__div = function(a, b)
return {x = a.x / b, y = a.y / b}
end
}
setmetatable(vector, meta)
local divided = vector / 2
print(divided.x, divided.y) -- Đầu ra: 1.5 2Các metamethod này hoàn thiện các phép toán số học cơ bản cho những kiểu dữ liệu tùy chỉnh của bạn, giúp bạn kiểm soát hoàn toàn cách các toán tử toán học hoạt động với các bảng của mình.
Thử thách
DễViết một hàm scaleVector nhận x, y và scalar, rồi trả về vectơ đã được nhân theo tỉ lệ dưới dạng chuỗi có định dạng.
Tạo một bảng vectơ với các tọa độ đã cho, gắn một metatable có metamethod __mul để cho phép nhân với số vô hướng, nhân vectơ với số vô hướng bằng toán tử *, rồi trả về kết quả.
Logic:
- Tạo một bảng vectơ với các khóa
xvàyđược gán tọa độ đã cho - Tạo một metatable có
__mulđể xử lý phép nhân giữa vectơ và số vô hướng - Hàm
__mulcần kiểm tra toán hạng nào là số và toán hạng nào là bảng - Trả về một bảng mới với
x = vec.x * scalarvày = vec.y * scalar - Gắn metatable vào bảng vectơ bằng
setmetatable() - Nhân vectơ với số vô hướng bằng
vector * scalar - Trả về kết quả dưới dạng chuỗi theo định dạng
"x y"(giá trị x và y cách nhau bằng một dấu cách)
Tham số:
x(number): Tọa độ x của vectơy(number): Tọa độ y của vectơscalar(number): Giá trị số vô hướng dùng để nhân vectơ
Giá trị trả về: Vectơ đã được nhân theo tỉ lệ dưới dạng chuỗi theo định dạng "x y" (chuỗi)
Tự làm thử
function scaleVector(x, y, scalar)
-- Viết code ở đây
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 Logic và luồng chương trình
4Giới thiệu về metatable
Metatable là gì?setmetatable và getmetatableMetamethod __indexMetamethod __newindexMetamethod __tostringMetamethod số học phần 1Metamethod số học phần 2Ôn tập: bảng chỉ đọc2Các hàm khác của thư viện table
table.concat()Tạo table và unpack()table.sort()Sắp xếp tùy chỉnh bằng hàmÔn tập: Bảng điểm cao5Dự án: Bộ máy trò chơi phiêu lưu bằng văn bản
Thiết lập dự án: Căn phòngLiên kết các phòngTự luyện tập: Trình biên dịch Lua online