Lua - Metatables
Khả năng đáp ứng là một bảng giúp sửa đổi hành vi của bảng mà nó được gắn vào với sự trợ giúp của tập khóa và các phương thức meta liên quan. Các phương thức meta này là chức năng Lua mạnh mẽ cho phép các tính năng như -
Thay đổi / thêm chức năng cho các toán tử trên bảng.
Tìm kiếm các dữ liệu có thể đo được khi khóa không có sẵn trong bảng bằng cách sử dụng __index trong metatable.
Có hai phương pháp quan trọng được sử dụng để xử lý các bảng đo lường bao gồm:
setmetatable(table,metatable) - Phương pháp này được sử dụng để thiết lập độ chính xác cho một bảng.
getmetatable(table) - Phương pháp này được sử dụng để lấy độ phân giải của một bảng.
Trước tiên, hãy xem cách đặt một bảng giống như một bảng khác. Nó được hiển thị bên dưới.
mytable = {}
mymetatable = {}
setmetatable(mytable,mymetatable)
Đoạn mã trên có thể được biểu diễn trong một dòng như hình dưới đây.
mytable = setmetatable({},{})
_mục lục
Dưới đây là một ví dụ đơn giản về việc tra cứu bảng meta khi nó không có sẵn trong bảng.
mytable = setmetatable({key1 = "value1"}, {
__index = function(mytable, key)
if key == "key2" then
return "metatablevalue"
else
return mytable[key]
end
end
})
print(mytable.key1,mytable.key2)
Khi chúng ta chạy chương trình trên, chúng ta sẽ nhận được kết quả sau.
value1 metatablevalue
Hãy để chúng tôi giải thích những gì đã xảy ra trong ví dụ trên theo các bước.
Bảng mytable ở đây là {key1 = "value1"}.
Metatable được đặt cho mytable có chứa hàm cho __index, mà chúng tôi gọi là metamethod.
Metamethod thực hiện một công việc đơn giản là tìm kiếm một chỉ mục "key2", nếu nó được tìm thấy, nó sẽ trả về "metatablevalue", nếu không thì trả về giá trị của mytable cho chỉ mục tương ứng.
Chúng ta có thể có một phiên bản đơn giản của chương trình trên như hình dưới đây.
mytable = setmetatable({key1 = "value1"},
{ __index = { key2 = "metatablevalue" } })
print(mytable.key1,mytable.key2)
__newindex
Khi chúng ta thêm __newindex vào metatable, nếu các khóa không có sẵn trong bảng, thì hoạt động của các khóa mới sẽ được xác định bằng các phương thức meta. Dưới đây là một ví dụ đơn giản trong đó chỉ mục của metatable được đặt khi chỉ mục không có sẵn trong bảng chính.
mymetatable = {}
mytable = setmetatable({key1 = "value1"}, { __newindex = mymetatable })
print(mytable.key1)
mytable.newkey = "new value 2"
print(mytable.newkey,mymetatable.newkey)
mytable.key1 = "new value 1"
print(mytable.key1,mymetatable.newkey1)
Khi bạn chạy chương trình trên, bạn nhận được kết quả sau.
value1
nil new value 2
new value 1 nil
Bạn có thể thấy trong chương trình trên, nếu một khóa tồn tại trong bảng chính, nó chỉ cập nhật nó. Khi một khóa không có sẵn trong phần có thể bảo trì, nó sẽ thêm khóa đó vào phần có thể đo được.
Một ví dụ khác cập nhật cùng một bảng bằng cách sử dụng hàm rawset được hiển thị bên dưới.
mytable = setmetatable({key1 = "value1"}, {
__newindex = function(mytable, key, value)
rawset(mytable, key, "\""..value.."\"")
end
})
mytable.key1 = "new value"
mytable.key2 = 4
print(mytable.key1,mytable.key2)
Khi chúng ta chạy chương trình trên, chúng ta sẽ nhận được kết quả sau.
new value "4"
rawset đặt giá trị mà không sử dụng __newindex có thể đo được. Tương tự, có rawget nhận giá trị mà không cần sử dụng __index.
Thêm hành vi của người vận hành vào bảng
Dưới đây là một ví dụ đơn giản để kết hợp hai bảng bằng cách sử dụng + toán tử:
mytable = setmetatable({ 1, 2, 3 }, {
__add = function(mytable, newtable)
for i = 1, table.maxn(newtable) do
table.insert(mytable, table.maxn(mytable)+1,newtable[i])
end
return mytable
end
})
secondtable = {4,5,6}
mytable = mytable + secondtable
for k,v in ipairs(mytable) do
print(k,v)
end
Khi chúng ta chạy chương trình trên, chúng ta sẽ nhận được kết quả sau.
1 1
2 2
3 3
4 4
5 5
6 6
Khóa __add được bao gồm trong phép đo lường để thêm hành vi của toán tử +. Bảng các phím và toán tử tương ứng được hiển thị bên dưới.
Sr.No. | Chế độ & Mô tả |
---|---|
1 | __add Thay đổi hành vi của toán tử '+'. |
2 | __sub Thay đổi hành vi của toán tử '-'. |
3 | __mul Thay đổi hành vi của toán tử '*'. |
4 | __div Thay đổi hành vi của toán tử '/'. |
5 | __mod Thay đổi hành vi của toán tử '%'. |
6 | __unm Thay đổi hành vi của toán tử '-'. |
7 | __concat Thay đổi hành vi của toán tử '..'. |
số 8 | __eq Thay đổi hành vi của toán tử '=='. |
9 | __lt Thay đổi hành vi của toán tử '<'. |
10 | __le Thay đổi hành vi của toán tử '<='. |
__gọi
Thêm hành vi của cuộc gọi phương thức được thực hiện bằng cách sử dụng câu lệnh __call. Một ví dụ đơn giản trả về tổng các giá trị trong bảng chính với bảng đã truyền.
mytable = setmetatable({10}, {
__call = function(mytable, newtable)
sum = 0
for i = 1, table.maxn(mytable) do
sum = sum + mytable[i]
end
for i = 1, table.maxn(newtable) do
sum = sum + newtable[i]
end
return sum
end
})
newtable = {10,20,30}
print(mytable(newtable))
Khi chúng ta chạy chương trình trên, chúng ta sẽ nhận được kết quả sau.
70
__tostring
Để thay đổi hành vi của câu lệnh print, chúng ta có thể sử dụng metamethod __tostring. Một ví dụ đơn giản được hiển thị bên dưới.
mytable = setmetatable({ 10, 20, 30 }, {
__tostring = function(mytable)
sum = 0
for k, v in pairs(mytable) do
sum = sum + v
end
return "The sum of values in the table is " .. sum
end
})
print(mytable)
Khi chúng ta chạy chương trình trên, chúng ta sẽ nhận được kết quả sau.
The sum of values in the table is 60
Nếu bạn biết đầy đủ các khả năng của bảng meta, bạn thực sự có thể thực hiện nhiều thao tác sẽ rất phức tạp mà không cần sử dụng đến nó. Vì vậy, hãy cố gắng làm việc nhiều hơn với việc sử dụng các bảng đo lường với các tùy chọn khác nhau có sẵn trong bảng meta như được giải thích trong các mẫu và cũng tạo mẫu của riêng bạn.