Menu
CoddyTech

Metamethod số học phần 1

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 21 trên 54.

Bạn đã học cách tùy chỉnh nội dung hiển thị khi in một bảng bằng __tostring. Giờ đây, bạn sẽ khám phá cách metatable cũng có thể xác định điều gì xảy ra khi bạn dùng các toán tử số học như + và - với các bảng.

Thông thường, nếu bạn thử cộng hai bảng bằng toán tử +, Lua sẽ báo lỗi vì nó không biết cách cộng các bảng. Nhưng với các metamethod số học, bạn có thể định nghĩa chính xác phép cộng có nghĩa là gì đối với các kiểu dữ liệu tùy chỉnh của mình.

Metamethod __add điều khiển cách phép cộng hoạt động. Khi Lua gặp toán tử + giữa hai giá trị và ít nhất một giá trị có metatable chứa __add, Lua gọi hàm đó thay vì báo lỗi:

local v1 = {x = 3, y = 4}
local v2 = {x = 1, y = 2}

local meta = {
    __add = function(a, b)
        return {x = a.x + b.x, y = a.y + b.y}
    end
}

setmetatable(v1, meta)
setmetatable(v2, meta)

local v3 = v1 + v2
print(v3.x, v3.y)  -- Đầu ra: 4  6

Hàm __add nhận hai đối số: toán hạng bên trái và toán hạng bên phải. Trong ví dụ này, hàm tạo một bảng mới với các giá trị x và y là tổng của các giá trị tương ứng từ cả hai bảng đầu vào.

Tương tự, phương thức siêu dữ liệu __sub điều khiển phép trừ bằng toán tử -:

local meta = {
    __sub = function(a, b)
        return {x = a.x - b.x, y = a.y - b.y}
    end
}

setmetatable(v1, meta)
setmetatable(v2, meta)

local v3 = v1 - v2
print(v3.x, v3.y)  -- Đầu ra: 2  2

Khả năng định nghĩa hành vi tùy chỉnh cho toán tử này được gọi là nạp chồng toán tử (operator overloading).

challenge icon

Thử thách

Dễ

Viết một hàm addVectors nhận x1, y1, x2 và y2, rồi trả về kết quả cộng hai vector.

Tạo hai bảng vector với tọa độ đã cho, gắn metatable có phương thức metamethod __add để cho phép cộng vector, cộng chúng bằng toán tử +, rồi trả về kết quả dưới dạng chuỗi được định dạng.

Logic:

  • Tạo bảng vector thứ nhất với các khóa x = x1 và y = y1
  • Tạo bảng vector thứ hai với các khóa x = x2 và y = y2
  • Tạo một metatable có __add, nhận hai vector và trả về một bảng mới với x = a.x + b.x và y = a.y + b.y
  • Gắn metatable vào cả hai bảng vector bằng setmetatable()
  • Cộng hai vector bằng v1 + v2
  • Trả về kết quả dưới dạng chuỗi theo định dạng "x y" (giá trị x và y được phân cách bằng một dấu cách)

Tham số:

  • x1 (number): Tọa độ x của vector thứ nhất
  • y1 (number): Tọa độ y của vector thứ nhất
  • x2 (number): Tọa độ x của vector thứ hai
  • y2 (number): Tọa độ y của vector thứ hai

Giá trị trả về: Tổng của hai vector dưới dạng chuỗi theo định dạng "x y" (chuỗi)

Tự làm thử

function addVectors(x1, y1, x2, y2)
    -- 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