Lua 实现单例 (userdata) 多继承单例

来源:互联网 发布:类似于onedrive的软件 编辑:程序博客网 时间:2024/05/21 19:44
--region *.lua--Date --Author WikiChen--[[* 单例* 类似 c/c++ 单例模式* 实现类可以 继承它,实现单例* Note 需要实现 初始化函数 Init--]]--local Singleton = class("Singleton")local Singleton = {}--function Singleton:ctor()--    self:Release()--    self:onCreate()--endlocal setmetatableindex = function(t, index)    if type(t) == "userdata" then        local peer = tolua.getpeer(t)        if not peer then            peer = {}            tolua.setpeer(t, peer)        end        setmetatableindex(peer, index)    else        local mt = getmetatable(t)        if not mt then mt = {} end        if not mt.__index then            mt.__index = index            setmetatable(t, mt)        elseif mt.__index ~= index then            setmetatableindex(mt, index)        end    endendfunction Singleton:onCreate(obj)    obj = obj or {}    setmetatable(obj, self)    self.__index = self    return objendfunction Singleton:Instance()    if nil == self._instance then        self._instance = self:new()        setmetatableindex(self._instance, self)        self._instance:init()    end    return self._instanceendfunction Singleton:Release()    if nil ~= self._instance then        self._instance = nil    endendfunction Singleton:init()    print("Error, enter Singleton:init")endreturn Singleton--endregion

—————————————————————————————–

–[[
以下抄录自cocos2d-lua 中 function.lua
–]]

--[[Copyright (c) 2011-2014 chukong-inc.comPermission is hereby granted, free of charge, to any person obtaining a copyof this software and associated documentation files (the "Software"), to dealin the Software without restriction, including without limitation the rightsto use, copy, modify, merge, publish, distribute, sublicense, and/or sellcopies of the Software, and to permit persons to whom the Software isfurnished to do so, subject to the following conditions:The above copyright notice and this permission notice shall be included inall copies or substantial portions of the Software.THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS ORIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THEAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHERLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS INTHE SOFTWARE.]]function printLog(tag, fmt, ...)    local t = {        "[",        string.upper(tostring(tag)),        "] ",        string.format(tostring(fmt), ...)    }    print(table.concat(t))endfunction printError(fmt, ...)    printLog("ERR", fmt, ...)    print(debug.traceback("", 2))endfunction printInfo(fmt, ...)    if type(DEBUG) ~= "number" or DEBUG < 2 then return end    printLog("INFO", fmt, ...)endlocal function dump_value_(v)    if type(v) == "string" then        v = "\"" .. v .. "\""    end    return tostring(v)endfunction dump(value, desciption, nesting)    if type(nesting) ~= "number" then nesting = 3 end    local lookupTable = {}    local result = {}    local traceback = string.split(debug.traceback("", 2), "\n")    print("dump from: " .. string.trim(traceback[3]))    local function dump_(value, desciption, indent, nest, keylen)        desciption = desciption or "<var>"        local spc = ""        if type(keylen) == "number" then            spc = string.rep(" ", keylen - string.len(dump_value_(desciption)))        end        if type(value) ~= "table" then            result[#result +1 ] = string.format("%s%s%s = %s", indent, dump_value_(desciption), spc, dump_value_(value))        elseif lookupTable[tostring(value)] then            result[#result +1 ] = string.format("%s%s%s = *REF*", indent, dump_value_(desciption), spc)        else            lookupTable[tostring(value)] = true            if nest > nesting then                result[#result +1 ] = string.format("%s%s = *MAX NESTING*", indent, dump_value_(desciption))            else                result[#result +1 ] = string.format("%s%s = {", indent, dump_value_(desciption))                local indent2 = indent.."    "                local keys = {}                local keylen = 0                local values = {}                for k, v in pairs(value) do                    keys[#keys + 1] = k                    local vk = dump_value_(k)                    local vkl = string.len(vk)                    if vkl > keylen then keylen = vkl end                    values[k] = v                end                table.sort(keys, function(a, b)                    if type(a) == "number" and type(b) == "number" then                        return a < b                    else                        return tostring(a) < tostring(b)                    end                end)                for i, k in ipairs(keys) do                    dump_(values[k], k, indent2, nest + 1, keylen)                end                result[#result +1] = string.format("%s}", indent)            end        end    end    dump_(value, desciption, "- ", 1)    for i, line in ipairs(result) do        print(line)    endendfunction printf(fmt, ...)    print(string.format(tostring(fmt), ...))endfunction checknumber(value, base)    return tonumber(value, base) or 0endfunction checkint(value)    return math.round(checknumber(value))endfunction checkbool(value)    return (value ~= nil and value ~= false)endfunction checktable(value)    if type(value) ~= "table" then value = {} end    return valueendfunction isset(hashtable, key)    local t = type(hashtable)    return (t == "table" or t == "userdata") and hashtable[key] ~= nilendlocal setmetatableindex_setmetatableindex_ = function(t, index)    if type(t) == "userdata" then        local peer = tolua.getpeer(t)        if not peer then            peer = {}            tolua.setpeer(t, peer)        end        setmetatableindex_(peer, index)    else        local mt = getmetatable(t)        if not mt then mt = {} end        if not mt.__index then            mt.__index = index            setmetatable(t, mt)        elseif mt.__index ~= index then            setmetatableindex_(mt, index)        end    endendsetmetatableindex = setmetatableindex_function clone(object)    local lookup_table = {}    local function _copy(object)        if type(object) ~= "table" then            return object        elseif lookup_table[object] then            return lookup_table[object]        end        local newObject = {}        lookup_table[object] = newObject        for key, value in pairs(object) do            newObject[_copy(key)] = _copy(value)        end        return setmetatable(newObject, getmetatable(object))    end    return _copy(object)endfunction class(classname, ...)    local cls = {__cname = classname}    local supers = {...}    for _, super in ipairs(supers) do        local superType = type(super)        assert(superType == "nil" or superType == "table" or superType == "function",            string.format("class() - create class \"%s\" with invalid super class type \"%s\"",                classname, superType))        if superType == "function" then            assert(cls.__create == nil,                string.format("class() - create class \"%s\" with more than one creating function",                    classname));            -- if super is function, set it to __create            cls.__create = super        elseif superType == "table" then            if super[".isclass"] then                -- super is native class                assert(cls.__create == nil,                    string.format("class() - create class \"%s\" with more than one creating function or native class",                        classname));                cls.__create = function() return super:create() end            else                -- super is pure lua class                cls.__supers = cls.__supers or {}                cls.__supers[#cls.__supers + 1] = super                if not cls.super then                    -- set first super pure lua class as class.super                    cls.super = super                end            end        else            error(string.format("class() - create class \"%s\" with invalid super type",                        classname), 0)        end    end    cls.__index = cls    if not cls.__supers or #cls.__supers == 1 then        setmetatable(cls, {__index = cls.super})    else        setmetatable(cls, {__index = function(_, key)            local supers = cls.__supers            for i = 1, #supers do                local super = supers[i]                if super[key] then return super[key] end            end        end})    end    if not cls.ctor then        -- add default constructor        cls.ctor = function() end    end    cls.new = function(...)        local instance        if cls.__create then            instance = cls.__create(...)        else            instance = {}        end        setmetatableindex(instance, cls)        instance.class = cls        instance:ctor(...)        return instance    end    cls.create = function(_, ...)        return cls.new(...)    end    return clsendlocal iskindof_iskindof_ = function(cls, name)    local __index = rawget(cls, "__index")    if type(__index) == "table" and rawget(__index, "__cname") == name then return true end    if rawget(cls, "__cname") == name then return true end    local __supers = rawget(cls, "__supers")    if not __supers then return false end    for _, super in ipairs(__supers) do        if iskindof_(super, name) then return true end    end    return falseendfunction iskindof(obj, classname)    local t = type(obj)    if t ~= "table" and t ~= "userdata" then return false end    local mt    if t == "userdata" then        if tolua.iskindof(obj, classname) then return true end        mt = tolua.getpeer(obj)    else        mt = getmetatable(obj)    end    if mt then        return iskindof_(mt, classname)    end    return falseendfunction import(moduleName, currentModuleName)    local currentModuleNameParts    local moduleFullName = moduleName    local offset = 1    while true do        if string.byte(moduleName, offset) ~= 46 then -- .            moduleFullName = string.sub(moduleName, offset)            if currentModuleNameParts and #currentModuleNameParts > 0 then                moduleFullName = table.concat(currentModuleNameParts, ".") .. "." .. moduleFullName            end            break        end        offset = offset + 1        if not currentModuleNameParts then            if not currentModuleName then                local n,v = debug.getlocal(3, 1)                currentModuleName = v            end            currentModuleNameParts = string.split(currentModuleName, ".")        end        table.remove(currentModuleNameParts, #currentModuleNameParts)    end    return require(moduleFullName)endfunction handler(obj, method)    return function(...)        return method(obj, ...)    endendfunction math.newrandomseed()    local ok, socket = pcall(function()        return require("socket")    end)    if ok then        math.randomseed(socket.gettime() * 1000)    else        math.randomseed(os.time())    end    math.random()    math.random()    math.random()    math.random()endfunction math.round(value)    value = checknumber(value)    return math.floor(value + 0.5)endlocal pi_div_180 = math.pi / 180function math.angle2radian(angle)    return angle * pi_div_180endlocal pi_mul_180 = math.pi * 180function math.radian2angle(radian)    return radian / pi_mul_180endfunction io.exists(path)    local file = io.open(path, "r")    if file then        io.close(file)        return true    end    return falseendfunction io.readfile(path)    local file = io.open(path, "r")    if file then        local content = file:read("*a")        io.close(file)        return content    end    return nilendfunction io.writefile(path, content, mode)    mode = mode or "w+b"    local file = io.open(path, mode)    if file then        if file:write(content) == nil then return false end        io.close(file)        return true    else        return false    endendfunction io.pathinfo(path)    local pos = string.len(path)    local extpos = pos + 1    while pos > 0 do        local b = string.byte(path, pos)        if b == 46 then -- 46 = char "."            extpos = pos        elseif b == 47 then -- 47 = char "/"            break        end        pos = pos - 1    end    local dirname = string.sub(path, 1, pos)    local filename = string.sub(path, pos + 1)    extpos = extpos - pos    local basename = string.sub(filename, 1, extpos - 1)    local extname = string.sub(filename, extpos)    return {        dirname = dirname,        filename = filename,        basename = basename,        extname = extname    }endfunction io.filesize(path)    local size = false    local file = io.open(path, "r")    if file then        local current = file:seek()        size = file:seek("end")        file:seek("set", current)        io.close(file)    end    return sizeendfunction table.nums(t)    local count = 0    for k, v in pairs(t) do        count = count + 1    end    return countendfunction table.keys(hashtable)    local keys = {}    for k, v in pairs(hashtable) do        keys[#keys + 1] = k    end    return keysendfunction table.values(hashtable)    local values = {}    for k, v in pairs(hashtable) do        values[#values + 1] = v    end    return valuesendfunction table.merge(dest, src)    for k, v in pairs(src) do        dest[k] = v    endendfunction table.insertto(dest, src, begin)    begin = checkint(begin)    if begin <= 0 then        begin = #dest + 1    end    local len = #src    for i = 0, len - 1 do        dest[i + begin] = src[i + 1]    endendfunction table.indexof(array, value, begin)    for i = begin or 1, #array do        if array[i] == value then return i end    end    return falseendfunction table.keyof(hashtable, value)    for k, v in pairs(hashtable) do        if v == value then return k end    end    return nilendfunction table.removebyvalue(array, value, removeall)    local c, i, max = 0, 1, #array    while i <= max do        if array[i] == value then            table.remove(array, i)            c = c + 1            i = i - 1            max = max - 1            if not removeall then break end        end        i = i + 1    end    return cendfunction table.map(t, fn)    for k, v in pairs(t) do        t[k] = fn(v, k)    endendfunction table.walk(t, fn)    for k,v in pairs(t) do        fn(v, k)    endendfunction table.filter(t, fn)    for k, v in pairs(t) do        if not fn(v, k) then t[k] = nil end    endendfunction table.unique(t, bArray)    local check = {}    local n = {}    local idx = 1    for k, v in pairs(t) do        if not check[v] then            if bArray then                n[idx] = v                idx = idx + 1            else                n[k] = v            end            check[v] = true        end    end    return nendstring._htmlspecialchars_set = {}string._htmlspecialchars_set["&"] = "&amp;"string._htmlspecialchars_set["\""] = "&quot;"string._htmlspecialchars_set["'"] = "&#039;"string._htmlspecialchars_set["<"] = "&lt;"string._htmlspecialchars_set[">"] = "&gt;"function string.htmlspecialchars(input)    for k, v in pairs(string._htmlspecialchars_set) do        input = string.gsub(input, k, v)    end    return inputendfunction string.restorehtmlspecialchars(input)    for k, v in pairs(string._htmlspecialchars_set) do        input = string.gsub(input, v, k)    end    return inputendfunction string.nl2br(input)    return string.gsub(input, "\n", "<br />")endfunction string.text2html(input)    input = string.gsub(input, "\t", "    ")    input = string.htmlspecialchars(input)    input = string.gsub(input, " ", "&nbsp;")    input = string.nl2br(input)    return inputendfunction string.split(input, delimiter)    input = tostring(input)    delimiter = tostring(delimiter)    if (delimiter=='') then return false end    local pos,arr = 0, {}    -- for each divider found    for st,sp in function() return string.find(input, delimiter, pos, true) end do        table.insert(arr, string.sub(input, pos, st - 1))        pos = sp + 1    end    table.insert(arr, string.sub(input, pos))    return arrendfunction string.ltrim(input)    return string.gsub(input, "^[ \t\n\r]+", "")endfunction string.rtrim(input)    return string.gsub(input, "[ \t\n\r]+$", "")endfunction string.trim(input)    input = string.gsub(input, "^[ \t\n\r]+", "")    return string.gsub(input, "[ \t\n\r]+$", "")endfunction string.ucfirst(input)    return string.upper(string.sub(input, 1, 1)) .. string.sub(input, 2)endlocal function urlencodechar(char)    return "%" .. string.format("%02X", string.byte(char))endfunction string.urlencode(input)    -- convert line endings    input = string.gsub(tostring(input), "\n", "\r\n")    -- escape all characters but alphanumeric, '.' and '-'    input = string.gsub(input, "([^%w%.%- ])", urlencodechar)    -- convert spaces to "+" symbols    return string.gsub(input, " ", "+")endfunction string.urldecode(input)    input = string.gsub (input, "+", " ")    input = string.gsub (input, "%%(%x%x)", function(h) return string.char(checknumber(h,16)) end)    input = string.gsub (input, "\r\n", "\n")    return inputendfunction string.utf8len(input)    local len  = string.len(input)    local left = len    local cnt  = 0    local arr  = {0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc}    while left ~= 0 do        local tmp = string.byte(input, -left)        local i   = #arr        while arr[i] do            if tmp >= arr[i] then                left = left - i                break            end            i = i - 1        end        cnt = cnt + 1    end    return cntendfunction string.formatnumberthousands(num)    local formatted = tostring(checknumber(num))    local k    while true do        formatted, k = string.gsub(formatted, "^(-?%d+)(%d%d%d)", '%1,%2')        if k == 0 then break end    end    return formattedend
原创粉丝点击