Metatablolar

*Bu içerik, yapay zekâ (beta) kullanılarak çevrildi ve hatalar içerebilir. Sayfayı İngilizce görüntülemek için buraya tıkla.

Metatablolar, tabloların öncekinden daha güçlü hale gelmesini sağlar. Verilere eklenirler ve metamethod adı verilen değerleri içerirler. Metamethod'lar, bağlı oldukları veri ile belirli bir eylem gerçekleştirildiğinde tetiklenir.

Metatabloları Manipüle Etme

Bir tablonun metatabasını eklemek ve bulmak için iki temel fonksiyon setmetatable() ve getmetatable()'dır.


local x = {}
local metaTable = {} -- Metatablolar da tablodur!
setmetatable(x, metaTable) -- x'e metaTable adında bir metatable ver!
print(getmetatable(x)) --> table: [hexadecimal bellek adresi]

setmetatable() fonksiyonu, metatable'ı ayarladığınız tabloyu da döndürdüğü için, bu iki script aynı şeyi yapar:


local x = {}
setmetatable(x, {})

local x = setmetatable({}, {})

Metamethod'lar

Metamethod'lar, bir metatable içerisinde saklanan işlevlerdir. Tablo çağırmaktan, tablolara toplama yapmaya ve hatta tabloları bölmeye kadar çeşitli işlemler için kullanılabilirler. İşte mevcut metamethod'ların listesi:

MetodAçıklama
__index(table, index)table[index] dizinlendiğinde tetiklenir, eğer table[index] nil ise. Ayrıca bir tabloya da ayarlanabilir, bu durumda o tablo dizinlenecektir.
__newindex(table, index, value)table[index] ayarlanmaya çalışıldığında tetiklenir (table[index] = value), eğer table[index] nil ise. Ayrıca bir tabloya da ayarlanabilir, bu durumda o tablo dizinlenecektir.
__call(table, ...)Tablo bir fonksiyon gibi çağrıldığında tetiklenir, ... ile geçirilen argümanlardır.
__concat(table, value).. birleştirme operatörü tablo üzerinde kullanıldığında tetiklenir.
__unm(table)Tekil operatörü tablo üzerinde kullanıldığında tetiklenir.
__add(table, value)+ toplama operatörü.
__sub(table, value) çıkarma operatörü.
__mul(table, value)* çarpma operatörü.
__div(table, value)/ bölme operatörü.
__idiv(table, value)// tam sayı bölme operatörü.
__mod(table, value)% modül operatörü.
__pow(table, value)^ üstel operatörü.
__tostring(table)tostring tablosu çağrıldığında tetiklenir.
__metatableVarlığı halinde, metatable'ı kilitler, böylece getmetatable() bu değeri döndürür ve setmetatable() hata verir. Fonksiyon olmayan değer.
__eq(table, value)== eşitlik operatörü¹
__lt(table, value)< küçüktür operatörü¹
__le(table, value)<= operatörü¹
__modeZayıf tablolarda kullanılan, bir tablonun anahtarlarının ve/veya değerlerinin zayıf olup olmadığını belirten bir bildirim. Roblox örneklerine yapılan referansların asla zayıf olmadığını unutmayın. Böyle referansları tutan tablolar asla çöp toplayıcı tarafından temizlenmeyeceklerdir.
__len(table)# uzunluk operatörü tablosu üzerinde kullanıldığında tetiklenir.
__iter(table)Genelleştirilmiş yineleme kullanırken özel bir yineleyiciyi belirtmek için kullanılır.

Aritmetik veya ilişkisel metamethod'lar için işlevler yazarken, iki işlev parametresinin, metamethod'ı tetikleyen tablonun ve diğer değerin yerini değiştirebildiği belirtilmelidir. Örneğin, skalar bölme işlemleriyle vektör işlemleri yaparken toplama işleminin değişimli olmadığına dikkat etmelisiniz. Bu nedenle, vector2 sınıfınız için metamethod'lar yazarken, her iki senaryoyu da hesaba katmanız önemlidir.


local vector2 = {__type = "vector2"}
local mt = {__index = vector2}
function mt.__div(a, b)
if type(a) == "number" then
-- a bir skalar, b bir vektör
local scalar, vector = a, b
return vector2.new(scalar / vector.x, scalar / vector.y)
elseif type(b) == "number" then
-- a bir vektör, b bir skalar
local vector, scalar = a, b
return vector2.new(vector.x / scalar, vector.y / scalar)
elseif (a.__type and a.__type == "vector2" and b.__type and b.__type == "vector2") then
-- a ve b her ikisi de vektörler
return vector2.new(a.x / b.x, a.y / b.y)
end
end
function mt.__tostring(t)
return t.x .. ", " .. t.y
end
function vector2.new(x, y)
local self = setmetatable({}, mt)
self.x = x or 0
self.y = y or 0
return self
end
local a = vector2.new(10, 5)
local b = vector2.new(-3, 4)
print(a / b) -- -3.3333333333333, 1.25
print(b / a) -- -0.3, 0.8
print(2 / a) -- 0.2, 0.4
print(a / 2) -- 5, 2.5

Kullanım

Metatabloları kullanmanın birçok yolu vardır; örneğin bir tabloyu negatif yapmak için __unm metamethod'unu kullanabilirsiniz:


local metatable = {
__unm = function(t) -- __unm tekil - operatörü için
local negated = {}
for key, value in t do
negated[key] = -value -- bu tablo içindeki tüm değerleri negatife çevirecek
end
return negated -- tabloyu geri döndür
end
}
local table1 = setmetatable({10, 11, 12}, metatable)
print(table.concat(-table1, "; ")) --> -10; -11; -12

__index kullanarak şeyleri başka bir ilginç şekilde tanımlamak:


local metatable = {
__index = {x = 1}
}
local t = setmetatable({}, metatable)
print(t.x) --> 1

t tablosunda x dizinlendiğinde, ve bulunamadığında __index tetiklenmiştir. Luau daha sonra __index tablosunda x adında bir dizin aradı ve bulunca değeri geri döndürdü.

Şimdi bunu basit bir işlevle kolayca yapabilirsiniz, ama bunun ötesinde daha birçok şey var. Buna bir örnek olarak:


local t = {10, 20, 30}
print(t(5))

Genellikle bir tabloyu çağırmanız mümkün değildir, ancak metatablolar sayesinde bunu yapabilirsiniz:


local metatable = {
__call = function(t, param)
local sum = {}
for i, value in ipairs(t) do
sum[i] = value + param -- Argümanı (5) değere ekle, ardından yeni tabloya (t) koy.
end
return unpack(sum) -- Bireysel tablo değerlerini geri döndür
end
}
local t = setmetatable({10, 20, 30}, metatable)
print(t(5)) --> 15 25 35

Aynı zamanda, tabloları eklemek gibi daha fazlasını da yapabiliriz:


local table1 = {10, 11, 12}
local table2 = {13, 14, 15}
for k, v in table1 + table2 do
print(k, v)
end

Bu, bir tablo üzerinde aritmetik işlem yapmaya çalıştığınız için hata verecektir, ancak bir metatable ile denerseniz çalışır:


local metatable = {
__add = function(t1, t2)
local sum = {}
for key, value in t1 do
sum[key] = value
end
for key, value in t2 do
if sum[key] then
sum[key] += value
else
sum[key] = value
end
end
return sum
end
}
local table1 = setmetatable({10, 11, 12}, metatable)
local table2 = setmetatable({13, 14, 15}, metatable)
for k, v in table1 + table2 do
print(k, v)
end

Metatablolarla oynarken bazı sorunlarla karşılaşabilirsiniz. Bir tabloya yeni değerler eklemek için __index metamethod'unu kullanmanız gerekiyorsa, ama o tablonun metatable'ında da __newindex metamethod'u varsa, bu durumu aşmak için rawset() yerleşik fonksiyonunu kullanmalısınız. Aşağıdaki kod, bu fonksiyonları kullanmazsanız ne olacağını göstermektedir.


local t = setmetatable({}, {
__index = function(self, i)
self[i] = i * 10
return self[i]
end,
__newindex = function(self, i, v)
-- Değerleri tabloya normal şekilde ayarlamayın
end
})
print(t[1]) -- Yığın taşması meydana gelir

Yığın taşmaları, bir fonksiyonu kendisinden çok fazla kez çağırmaya çalıştığınızda meydana gelir. Yukarıdaki __index fonksiyonunda, self[i] bir değere ayarlandığında, bir sonraki satıra geldiğinde self[i] var olmalı ve muhtemelen __index metamethod'unu çağırmayacak şekilde görülmelidir. Problem __newindex'in değeri ayarlamanıza izin vermemesidir. Varlığı, standart t[i] = v yöntemiyle tablonun içine değer eklenmesini durdurur. Bu durumu aşmak için rawset() fonksiyonunu kullanmalısınız:


local t = setmetatable({}, {
__index = function(self, i)
rawset(self, i, i * 10)
return self[i]
end,
__newindex = function(self, i, v)
-- Değerleri tabloya normal şekilde ayarlamayın
end
})
print(t[1]) --> 10

Set veri tipini kullanın

Set, sırasız ve tekrar eden elemanlar içermeyen bir öğe koleksiyonudur. Bir öğe ya vardır ya da yoktur setin içindedir. Metatablolar kullanarak, Luau scriptleri içinde setler oluşturabilir ve üzerinde işlem yapabilirsiniz.

Temel yöntemler

Aşağıdaki kod, yeni setler oluşturmanıza, bir öğe eklemenize ve çıkarmanıza, bir setin bir öğe içerip içermediğini kontrol etmenize ve bir setin içeriğini çıktısını almanıza olanak tanır.


local Set = {}
Set.__index = Set
-- Opsiyonel bir öğe listesi ile bir set oluşturma fonksiyonu
function Set.new(items)
local newSet = {}
for key, value in items or {} do
newSet[value] = true
end
return setmetatable(newSet, Set)
end
-- Bir öğeyi bir sete eklemek için fonksiyon
function Set:add(item)
self[item] = true
end
-- Bir öğeyi bir setten çıkarmak için fonksiyon
function Set:remove(item)
self[item] = nil
end
-- Bir setin içinde bir öğe olup olmadığını kontrol etme fonksiyonu
function Set:contains(item)
return self[item] == true
end
-- Seti hata ayıklama için virgülle ayrılmış bir liste olarak çıktı verme fonksiyonu
function Set:output()
local elems = {}
for key, value in self do
table.insert(elems, tostring(key))
end
print(table.concat(elems, ", "))
end

Set oluşturma

Yeni bir set oluşturmak için Set.new() fonksiyonunu opsiyonel bir öğe dizisi ile çağırabilirsiniz.


local fruits = Set.new({"Elma", "Limon", "Portakal", "Kiraz", "Lime", "Şeftali"})

Setin tanımı gereği, bir setin sıralama kavramı yoktur.

Öğeyi ekleme

Mevcut bir sete öğe eklemek, Set:add() yöntemi ile yapılabilir.


local fruits = Set.new({"Elma", "Limon", "Portakal", "Kiraz", "Lime", "Şeftali"})
fruits:add("Mango")

Öğeyi çıkarma

Bir setten bir öğeyi çıkarmak için, öğe adını kullanarak Set:remove() çağırabilirsiniz.


local fruits = Set.new({"Elma", "Limon", "Portakal", "Kiraz", "Lime", "Şeftali"})
fruits:remove("Portakal")

Öğeyi kontrol etme

Bir setin belirli bir öğeyi içerip içermediğini kontrol etmek için Set:contains() kullanın.


local fruits = Set.new({"Elma", "Limon", "Portakal", "Kiraz", "Lime", "Şeftali"})
local result1 = fruits:contains("Kiraz")
print(result1) -- true
local result2 = fruits:contains("Karpuz")
print(result2) -- false

Ek yöntemler

Setler için, öğeleri setler arasında karşılaştırmanıza, setleri birleştirmenize veya bir seti diğer bir setten çıkarmanıza izin veren başka yararlı işlemler de uygulanabilir.

Kesişim

Setleri Venn diyagramları olarak düşündüğünüzde, iki setin kesişimini şu şekilde alabilirsiniz; her iki set içinde de bulunan öğeler.


local function getIntersection(set1, set2)
local result = Set.new()
for key, value in set1 do
if set2:contains(key) then
result:add(key)
end
end
return result
end
local freshFruits = Set.new({"Mango", "Limon", "Portakal", "Kiraz", "Lime", "Şeftali"})
local frozenFruits = Set.new({"Mango", "Şeftali", "Ananas"})
local commonFruits = getIntersection(freshFruits, frozenFruits)
commonFruits:output() -- Mango, Şeftali

Birleşim

İki setin birleşimini almak için aşağıdaki fonksiyonu kullanabilirsiniz; yani, her iki set içinde bulunan öğelerin koleksiyonu, tekrar eden öğeler olmaksızın. Bu fonksiyon, set1 + set2 ekleme kısayolunu sağlamak için metatable __add yöntemini kullanır.


function Set:__add(otherSet)
local result = Set.new()
for entry in self do
result[entry] = true
end
for entry in otherSet do
result[entry] = true
end
return result
end
local sweetFruits = Set.new({"Elma", "Mango", "Kiraz", "Şeftali"})
local sourFruits = Set.new({"Limon", "Lime"})
local allFruits = sweetFruits + sourFruits
allFruits:output() -- Şeftali, Lime, Elma, Kiraz, Limon, Mango

Çıkarma

Bir setten diğer bir setin içerdiği tüm öğeleri çıkarmak için aşağıdaki fonksiyonu kullanabilirsiniz. Yukarıdaki fonksiyona benzer şekilde, bu metatable __sub yöntemini kullanarak set1 - set2 çıkarma kısayolu sağlar.


function Set:__sub(otherSet)
local result = Set.new()
for entry in self do
result[entry] = true
end
for entry in otherSet do
result[entry] = nil
end
return result
end
local allFruits = Set.new({"Elma", "Limon", "Mango", "Kiraz", "Lime", "Şeftali"})
local sourFruits = Set.new({"Limon", "Lime"})
local sweetFruits = allFruits - sourFruits
sweetFruits:output() -- Mango, Elma, Kiraz, Şeftali
©2026 Roblox Corporation. Roblox, the Roblox logo and Powering Imagination are among our registered and unregistered trademarks in the U.S. and other countries.