खोज…


वाक्य - विन्यास

  • [[स्थानीय] एमटी =] गेटमेटेबल ( टी ) -> ' टी ' के लिए संबद्ध मेटिबिटेबल को पुनः प्राप्त करें
  • [[स्थानीय] t =] समुच्चय ( t , mt ) -> ' t ' के लिए ' mt ' के लिए metatable सेट और ' t ' देता है

पैरामीटर

पैरामीटर विवरण
टी चर एक लावा तालिका का जिक्र; एक टेबल शाब्दिक भी हो सकता है।
mt एक मेटाटेबल के रूप में उपयोग करने के लिए टेबल; शून्य या अधिक मेटामेथोड फ़ील्ड सेट कर सकते हैं।

टिप्पणियों

यहां कुछ मेटामेथोड का उल्लेख नहीं है। पूरी सूची और उनके उपयोग के लिए, लुआ मैनुअल में संबंधित प्रविष्टि देखें।

मेटैटैबल्स का निर्माण और उपयोग

एक मेटाबॉलिज्म संचालन के एक सेट को परिभाषित करता है जो एक लुआ वस्तु के व्यवहार को बदल देता है। एक मेटाबॉलिक बस एक साधारण तालिका है, जिसका उपयोग एक विशेष तरीके से किया जाता है।

local meta = { } -- create a table for use as metatable

-- a metatable can change the behaviour of many things
-- here we modify the 'tostring' operation:
-- this fields should be a function with one argument.
-- it gets called with the respective object and should return a string
meta.__tostring = function (object)
    return string.format("{ %d, %d }", object.x, object.y)
end

-- create an object
local point = { x = 13, y = -2 }
-- set the metatable
setmetatable(point, meta)

-- since 'print' calls 'tostring', we can use it directly:
print(point) -- prints '{ 13, -2 }'

मेटामेथोड्स के रूप में तालिकाओं का उपयोग करना

कुछ मेटामेथोड को कार्य नहीं करना पड़ता है। इसके लिए सबसे महत्वपूर्ण उदाहरण __index । यह एक तालिका भी हो सकती है, जिसे तब लुकअप के रूप में उपयोग किया जाता है। यह आमतौर पर लुआ में कक्षाओं के निर्माण में उपयोग किया जाता है। यहाँ, एक तालिका (अक्सर मेटेबल स्वयं) का उपयोग कक्षा के सभी संचालन (तरीके) करने के लिए किया जाता है:

local meta = {}
-- set the __index method to the metatable.
-- Note that this can't be done in the constructor!
meta.__index = meta

function create_new(name)
    local self = { name = name }
    setmetatable(self, meta)
    return self
end

-- define a print function, which is stored in the metatable
function meta.print(self)
    print(self.name)
end

local obj = create_new("Hello from object")
obj:print()

कचरा संग्राहक - __gc मेटामेथोड

5.2

लुआ में वस्तुओं को एकत्र किया जाता है। कभी-कभी, आपको कुछ संसाधन मुक्त करने की आवश्यकता होती है, जब कोई वस्तु नष्ट हो जाती है (एकत्र), तो संदेश प्रिंट करना चाहते हैं या कुछ और करना चाहते हैं। इसके लिए, आप __gc उपयोग कर सकते हैं, जिसे ऑब्जेक्ट के नष्ट होने पर तर्क के साथ ऑब्जेक्ट के रूप में बुलाया जाता है। आप इस मेटामेथोड को एक प्रकार के विनाशकारी के रूप में देख सकते हैं।

यह उदाहरण __gc को कार्रवाई में दिखाता है। जब आंतरिक तालिका करने के लिए सौंपा t कचरा एकत्र हो जाता है, यह संदेश एकत्र किया जा रहा से पहले प्रिंट करता है। स्क्रिप्ट के अंत तक पहुंचने पर बाहरी तालिका के लिए इसी तरह:

local meta =
{
    __gc = function(self)
        print("destroying self: " .. self.name)
    end
}

local t = setmetatable({ name = "outer" }, meta)
do
    local t = { name = "inner" }
    setmetatable(t, meta)
end

अधिक मेटामेथोड्स

कई और मेटामेथोड हैं, उनमें से कुछ अंकगणित हैं (जैसे इसके अलावा, घटाव, गुणा), बिटवाइज़ ऑपरेशन हैं (और, या, एक्सोर, शिफ्ट), तुलना (<,>) और बुनियादी प्रकार जैसे == और # (समानता और लंबाई)। आओ हम एक वर्ग का निर्माण करें जो इनमें से कई कार्यों का समर्थन करता है: तर्कसंगत अंकगणित के लिए एक कॉल। जबकि यह बहुत बुनियादी है, यह विचार दिखाता है।

local meta = {
    -- string representation
    __tostring = function(self)
        return string.format("%s/%s", self.num, self.den)
    end,
    -- addition of two rationals
    __add = function(self, rhs)
        local num = self.num * rhs.den + rhs.num * self.den
        local den = self.den * rhs.den
        return new_rational(num, den)
    end,
    -- equality
    __eq = function(self, rhs)
        return self.num == rhs.num and self.den == rhs.den
    end
}

-- a function for the creation of new rationals
function new_rational(num, den)
    local self = { num = num, den = den }
    setmetatable(self, meta)

    return self
end

local r1 = new_rational(1, 2)
print(r1) -- 1/2

local r2 = new_rational(1, 3)
print(r1 + r2) -- 5/6

local r3 = new_rational(1, 2)
print(r1 == r3) -- true
-- this would be the behaviour if we hadn't implemented the __eq metamethod.
-- this compares the actual tables, which are different
print(rawequal(r1, r3)) -- false

तालिकाओं को कॉल करें

वहाँ एक metamethod कहा जाता है __call है, जो एक समारोह के रूप में इस्तेमाल किया जा रहा पर वस्तु की bevahiour को परिभाषित करता है, जैसे object() । इसका उपयोग फंक्शन ऑब्जेक्ट बनाने के लिए किया जा सकता है:

-- create the metatable with a __call metamethod
local meta = {
    __call = function(self)
        self.i = self.i + 1
    end,
    -- to view the results
    __tostring = function(self)
        return tostring(self.i)
    end
}

function new_counter(start)
    local self = { i = start }
    setmetatable(self, meta)
    return self
end

-- create a counter
local c = new_counter(1)
print(c) --> 1
-- call -> count up
c()
print(c) --> 2

मेटामेथोड को संबंधित वस्तु के साथ बुलाया जाता है, शेष सभी तर्कों को उसके बाद फ़ंक्शन में भेजा जाता है:

local meta = {
    __call = function(self, ...)
        print(self.prepend, ...)
    end
}

local self = { prepend = "printer:" }
setmetatable(self, meta)

self("foo", "bar", "baz")

तालिकाओं का अनुक्रमण

शायद मेटाबॉल का सबसे महत्वपूर्ण उपयोग तालिकाओं के अनुक्रमण को बदलने की संभावना है। इसके लिए, दो कार्यों पर विचार करना है: सामग्री पढ़ना और तालिका की सामग्री लिखना । ध्यान दें कि यदि तालिका में संबंधित कुंजी मौजूद नहीं है, तो दोनों क्रियाएं केवल ट्रिगर होती हैं।

पढ़ना

local meta = {}

-- to change the reading action, we need to set the '__index' method
-- it gets called with the corresponding table and the used key
-- this means that table[key] translates into meta.__index(table, key)
meta.__index = function(object, index)
    -- print a warning and return a dummy object
    print(string.format("the key '%s' is not present in object '%s'", index, object))
    return -1
end

-- create a testobject
local t = {}

-- set the metatable
setmetatable(t, meta)

print(t["foo"]) -- read a non-existent key, prints the message and returns -1

गैर-मौजूद कुंजी पढ़ते समय त्रुटि को बढ़ाने के लिए इसका उपयोग किया जा सकता है:

-- raise an error upon reading a non-existent key
meta.__index = function(object, index)
    error(string.format("the key '%s' is not present in object '%s'", index, object))
end

लिख रहे हैं

local meta = {}

-- to change the writing action, we need to set the '__newindex' method
-- it gets called with the corresponding table, the used key and the value
-- this means that table[key] = value translates into meta.__newindex(table, key, value)
meta.__newindex = function(object, index, value)
    print(string.format("writing the value '%s' to the object '%s' at the key '%s'",
                         value, object, index))
    --object[index] = value -- we can't do this, see below
end

-- create a testobject
local t = { }

-- set the metatable
setmetatable(t, meta)

-- write a key (this triggers the method)
t.foo = 42

अब आप अपने आप से पूछ सकते हैं कि तालिका में वास्तविक मूल्य कैसे लिखा गया है। इस मामले में, यह नहीं है। यहाँ समस्या यह है कि मेटामेथोड्स मेटामेथोड्स को ट्रिगर कर सकते हैं, जिसके परिणामस्वरूप इन्फिनिटिव लूप, या अधिक सटीक रूप से, स्टैक ओवरफ्लो होगा। तो हम इसे कैसे हल कर सकते हैं? इसके लिए समाधान को रॉ टेबल एक्सेस कहा जाता है।

कच्चे टेबल का उपयोग

कभी-कभी, आप मेटामेथोड्स को ट्रिगर नहीं करना चाहते हैं, लेकिन वास्तव में दिए गए कुंजी को लिख या पढ़ सकते हैं, एक्सेस के चारों ओर लिपटे कुछ चतुर कार्यों के बिना। इसके लिए, लुआ आपको कच्ची तालिका अभिगम विधि प्रदान करता है:

-- first, set up a metatable that allows no read/write access
local meta = {
    __index = function(object, index)
        -- raise an error
        error(string.format("the key '%s' is not present in object '%s'", index, object))
    end,
    __newindex = function(object, index, value)
        -- raise an error, this prevents any write access to the table
        error(string.format("you are not allowed to write the object '%s'", object))
    end
}

local t = { foo = "bar" }
setmetatable(t, meta)

-- both lines raise an error:
--print(t[1])
--t[1] = 42

-- we can now circumvent this problem by using raw access:
print(rawget(t, 1)) -- prints nil
rawset(t, 1, 42) -- ok

-- since the key 1 is now valid, we can use it in a normal manner:
print(t[1])

इसके साथ, अब हम ower पूर्व __newindex विधि को वास्तविक रूप से तालिका में मान लिखने के लिए फिर से लिख सकते हैं:

meta.__newindex = function(object, index, value)
    print(string.format("writing the value '%s' to the object '%s' at the key '%s'",
                         value, object, index))
    rawset(object, index, value)
end

OOP का अनुकरण

local Class = {} -- objects and classes will be tables
local __meta = {__index = Class}
-- ^ if an instance doesn't have a field, try indexing the class
function Class.new()
    -- return setmetatable({}, __meta) -- this is shorter and equivalent to:
    local new_instance = {}
    setmetatable(new_instance, __meta)
    return new_instance
end
function Class.print()
    print "I am an instance of 'class'"
end

local object = Class.new()
object.print() --> will print "I am an instance of 'class'"

ऑब्जेक्ट को पहले तर्क के रूप में पास करके उदाहरण विधियाँ लिखी जा सकती हैं।

-- append to the above example
function Class.sayhello(self)
    print("hello, I am ", self)
end
object.sayhello(object) --> will print "hello, I am <table ID>"
object.sayhello() --> will print "hello, I am nil"

इसके लिए कुछ सिंटैक्टिक शुगर है।

function Class:saybye(phrase)
    print("I am " .. self .. "\n" .. phrase)
end
object:saybye("c ya") --> will print "I am <table ID>
                      -->             c ya"

हम एक वर्ग में डिफ़ॉल्ट फ़ील्ड भी जोड़ सकते हैं।

local Class = {health = 100}
local __meta = {__index = Class}

function Class.new() return setmetatable({}, __meta) end
local object = Class.new()
print(object.health) --> prints 100
Class.health = 50; print(object.health) --> prints 50
-- this should not be done, but it illustrates lua indexes "Class"
-- when "object" doesn't have a certain field
object.health = 200 -- This does NOT index Class
print(object.health) --> prints 200


Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow