Menu
CoddyTech

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  8

Hã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  2

Cá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.

challenge icon

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 x và 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 __mul cầ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 * scalar và 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
quiz iconTự kiểm tra

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

Tự luyện tập: Trình biên dịch Lua online