Đây có phải là một số loại quy ước mà các lập trình viên Lua có kinh nghiệm đề xuất hoặc có lợi thế chính hãng để thực hiện theo cách này không?
Nó không phải là điển hình. Ưu điểm là trạng thái đối tượng là riêng tư, nhưng đó không đủ lợi thế để giới thiệu nó.
Tôi thấy mẫu này nhiều lần.
Tôi chưa bao giờ thấy trước đây và chỉ xảy ra một lần trong nguồn bạn đã đăng.
CHỈNH SỬA: Thêm câu trả lời cho câu hỏi được hỏi trong các nhận xét bên dưới bài đăng này.
Chức năng truy cập các biến cục bộ bên ngoài liên kết với các biến đó và được gọi là 'đóng cửa'. Lua (vì lý do lịch sử) đề cập đến những biến ràng buộc đó là 'upvalues'. Ví dụ:
local function counter()
local i = 1
return function()
print(i)
i = i + 1
end
end
local a, b = counter(), counter()
a() a() a() b() --> 1 2 3 1
a
và b
đang đóng cửa ràng buộc để bản khác nhau của i
, như bạn có thể nhìn thấy từ đầu ra. Nói cách khác, bạn có thể nghĩ về việc đóng cửa như một chức năng với trạng thái riêng tư của nó. Bạn có thể sử dụng để mô phỏng các đối tượng:
function Point(x,y)
local p = {}
function p.getX() -- syntax sugar for p.getX = function()
return x
end
function p.setX(x_)
x = x_
end
-- for brevity, not implementing a setter/getter for y
return p
end
p1 = Point(10,20)
p1.setX(50)
print(p1.getX())
Point
trả về một bảng đóng cửa, mỗi ràng buộc với người dân địa phương x
và y
. Bảng này không chứa trạng thái của điểm, bản thân các đóng bao làm, thông qua upvalues của họ. Một điểm quan trọng là mỗi lần Point
được gọi là nó tạo ra đóng cửa mới, không hiệu quả lắm nếu bạn có số lượng lớn đối tượng.
Một cách khác để tạo ra các lớp học trong Lua là để tạo ra các chức năng mà phải mất một bảng như là đối số đầu tiên, với trạng thái được lưu trữ trong bảng:
function Point(x,y)
local p = {x=x,y=y}
function p:getX() -- syntax sugar for p.getX = function(self)
return self.x
end
function p:setX(x)
self.x = x
end
return p
end
p1 = Point(10,20)
p1:setX(50) -- syntax sugar for p1.setX(p1, 50)
print(p1:getX()) -- syntax sugar for p1.getX(p1)
Cho đến nay, chúng tôi vẫn tạo ra các bản sao mới của mỗi phương pháp, nhưng bây giờ mà chúng ta không dựa vào upvalues cho nhà nước, chúng ta có thể khắc phục điều đó:
PointClass = {}
function PointClass:getX() return self.x end
function PointClass:setX(x) self.x = x end
function Point(x,y)
return {
x = x,
y = y,
getX = PointClass.getX,
setX = PointClass.getY,
}
end
Bây giờ các phương pháp được tạo ra một lần, và tất cả các trường hợp Point
chia sẻ việc đóng cửa tương tự. Một cách tốt hơn để làm điều này là sử dụng cơ sở lập trình meta Lua để làm mới Point
trường tự động tìm trong PointClass
vì đã không tìm thấy phương pháp trong trường hợp bản thân:
PointClass = {}
PointClass.__index = PointClass -- metamethod
function PointClass:getX() return self.x end
function PointClass:setX(x) self.x = x end
function Point(x,y)
return setmetatable({x=x,y=y}, PointClass)
end
p1 = Point(10,20)
-- the p1 table does not itself contain a setX member, but p1 has a metatable, so
-- when an indexing operation fails, Lua will look in the metatable for an __index
-- metamethod. If that metamethod is a table, Lua will look for getX in that table,
-- resolving p1.setX to PointClass.setX.
p1:setX(50)
Đây là một cách nhiều thành ngữ của việc tạo ra các lớp học trong Lua. Đó là bộ nhớ hiệu quả hơn và linh hoạt hơn (đặc biệt, nó làm cho nó dễ dàng để thực hiện kế thừa).
Bạn có chắc chắn đã đơn giản hóa nó đúng cách không? Bạn có thể liên kết với một số ví dụ này dưới dạng đầy đủ của họ không? – Amber
Vâng, 'mẫu' bạn đã đăng có vẻ hoàn toàn vô nghĩa. Bạn nói rằng bạn thấy rằng "rất nhiều", bạn có thể liên kết với một ví dụ? – Mud
Tôi đã chỉnh sửa câu hỏi với một ví dụ hoàn chỉnh hơn và được trích dẫn nơi bạn có thể tải xuống bản lưu trữ nguồn hoàn chỉnh. Nếu Lua giống như các ngôn ngữ khác tôi biết, có vẻ như hình thức thứ 2 làm nhiều hơn với ít hơn. –