Menu
CoddyTech

Cộng các đối tượng

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 26 trên 70.

Bạn đã thấy các metamethod như __tostring và __eq cho phép bạn tùy chỉnh cách các đối tượng hoạt động. Bây giờ, mình sẽ mở rộng điều này sang các phép toán số học, bắt đầu với phép cộng.

Metamethod __add xác định điều gì xảy ra khi bạn dùng toán tử + giữa hai đối tượng. Khi Lua gặp a + b, Lua tìm __add trong metatable của một trong hai toán hạng.

local Vector = {}
Vector.__index = Vector

function Vector:new(x, y)
    local obj = {x = x, y = y}
    setmetatable(obj, Vector)
    return obj
end

function Vector.__add(v1, v2)
    return Vector:new(v1.x + v2.x, v1.y + v2.y)
end

Lưu ý rằng __add được định nghĩa bằng dấu chấm. Lua truyền cả hai toán hạng dưới dạng đối số thông thường, còn dạng dấu chấm đặt tên cho cả hai đối số. Dấu hai chấm cũng dùng được, vì function Vector:__add(other) tương đương với function Vector.__add(self, other), nhưng dạng dấu chấm là quy ước. __add nên trả về một đối tượng mới thay vì sửa đổi một trong hai đối tượng ban đầu. Nhờ vậy, phép toán luôn dễ đoán và an toàn.

local a = Vector:new(3, 4)
local b = Vector:new(1, 2)
local c = a + b

print(c.x, c.y)  -- Đầu ra: 4  6

Điểm mấu chốt là __add phải nằm trong metatable (bảng siêu dữ liệu) itself, ở đây là Vector, chứ không chỉ nằm trong đối tượng. Vì ta đặt Vector làm metatable cho mọi instance, tất cả chúng tự động chia sẻ hành vi này.

challenge icon

Thử thách

Dễ

Hãy xây dựng một lớp Vector hỗ trợ phép cộng bằng toán tử +. Đây là bước đầu tiên để bạn tìm hiểu về việc nạp chồng toán tử, giúp các đối tượng hoạt động tự nhiên với những toán tử có sẵn trong Lua.

Bạn sẽ sắp xếp code trong hai tệp:

  • Vector.lua: Định nghĩa lớp Vector với các thành phần x và y. Thêm hàm khởi tạo :new(x, y) và triển khai metamethod __add để phép cộng hai vector tạo ra một vector mới có các thành phần là tổng tương ứng. Định nghĩa __add bằng dấu chấm để cả hai toán hạng được truyền vào dưới dạng đối số có tên.
  • main.lua: Yêu cầu module Vector, tạo các instance vector và minh họa rằng phép cộng chúng cho ra kết quả chính xác.

Bạn sẽ nhận bốn đầu vào:

  1. Thành phần x của vector thứ nhất
  2. Thành phần y của vector thứ nhất
  3. Thành phần x của vector thứ hai
  4. Thành phần y của vector thứ hai

Trong tệp chính, hãy tạo hai vector với các thành phần đã cho, cộng chúng bằng toán tử + và in các giá trị x và y của vector kết quả trên các dòng riêng biệt.

Ví dụ, nếu đầu vào là 3, 4, 1, 2, đầu ra sẽ là:

4
6

Vector thứ nhất (3, 4) cộng với vector thứ hai (1, 2) bằng vector mới (4, 6).

Tự làm thử

-- Nạp module Vector bằng require
local Vector = require('Vector')

-- Đọc dữ liệu đầu vào
local x1 = tonumber(io.read())
local y1 = tonumber(io.read())
local x2 = tonumber(io.read())
local y2 = tonumber(io.read())

-- TODO: Tạo hai instance Vector từ các giá trị đầu vào

-- TODO: Cộng hai vectơ bằng toán tử +

-- TODO: In các giá trị x và y của vectơ kết quả trên hai dòng riêng
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 Lập trình hướng đối tượng

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