zoukankan      html  css  js  c++  java
  • LUA类

    cpp_object_map = {}
    setmetatable(cpp_object_map, { __mode = "kv" })

    local search_base
    search_base = function(t, k)

    local base_list = rawget(t, "__base_list")

    if not base_list then
    return
    end

    local v
    for i = 1, #base_list do
    local base = base_list[i]

    v = rawget(base, k)
    if v then
    t[k] = v -- 缓存搜索结果
    return v
    end

    v = search_base(base, k)
    if v then
    t[k] = v -- 缓存搜索结果
    return v
    end
    end
    end


    is_class_type = function(obj)
    return type(obj) == "table" and obj.__class ~= nil
    end

    is_class_of = function(obj, class)
    return is_class_type(obj) and obj.__class == class
    end

    is_base_class = function(base, derive)
    local base_list = rawget(derive, "__base_list")

    if not base_list then return false end

    for _, b_class in ipairs(base_list) do
    if (base == b_class) or is_base_class(base, b_class) then
    return true
    end
    end

    return false
    end

    class_cast = function(Cls, Obj)
    -- 不允许子类往基类转,因为这样可能导致转完后的对象找不到子类上的函数
    if Obj.__class and is_base_class(Cls, Obj.__class) then
    return Obj
    end

    setmetatable(Obj, Cls.__objmt)
    Obj.__class = Cls
    return Obj
    end

     

    class = function(...)
    local arg = {...}
    local NewClass = {}

    NewClass.__base_list = {}
    for i = 1, #arg do
    if arg[i] == nil then
    error("定义class的函数传入的基类为nil!")
    end
    if type(arg[i]) ~= "table" or not arg[i].__objmt then
    error("定义class的函数传入的基类不是自定义类型!")
    end

    table.insert( NewClass.__base_list, arg[i] )

    -- 将基类记录到类的table里面用于查询继承关系
    NewClass[ arg[i] ] = true
    end
    -- 将基类记录到类的table里面用于查询继承关系
    NewClass[ NewClass ] = true

    NewClass.__prop_list = {}

    NewClass.__objmt = {//---1
    __index = function(self, key)
    if NewClass.__prop_list[key] then
    return NewClass.__prop_list[key](self)
    end
    return NewClass[key] ---2
    end,

    __newindex = function(self, key, value)
    if NewClass.__prop_list[key] then
    NewClass.__prop_list[key](self, value)
    else
    rawset(self, key, value)
    end
    end,

    -- __tostring = function(obj)
    -- return "<object of "..tostring(obj.__class).." (at "..rawget(obj, 3)..")>"
    -- end
    }

    NewClass.New = function(self, ...)--这里的self是指NewClass,当前表
    local LuaObj = {} --类的实例对象,其实也是一张表,每个新对象是一张独立的新表
    class_cast(NewClass, LuaObj)

    --在调用Ctor之前先把_CreateingInstance属性设置好,不然在Ctor里又引用自己的话就会导致额外创建。wellbye
    self._CreateingInstance = LuaObj

    --c++对象的构造
    if self.ctor then
    self.ctor(LuaObj)
    elseif self.__cppclass then
    error("C++类"..self.__name.."不允许在脚本层构造!")
    end

    -- lua类的初始化
    if self.Init then
    self.Init(LuaObj, ...)
    end

    self._CreateingInstance = nil
    return LuaObj
    end

    NewClass.copy = function(self, ...)
    local LuaObj = {}
    class_cast(NewClass, LuaObj)

    --在调用Ctor之前先把_CreateingInstance属性设置好,不然在Ctor里又引用自己的话就会导致额外创建。wellbye
    self._CreateingInstance = LuaObj

    local arg = {...}
    local src_obj = arg[1]
    if not is_class_type(src_obj) or (self ~= src_obj.__class and
    not is_base_class(self, src_obj.__class)) then
    error("参数类型错误,必须是"..tostring(self).."或其派生类的对象")
    end

    --c++对象的复制构造
    if self.copy_ctor then
    self.copy_ctor(LuaObj, src_obj)
    elseif self.__cppclass then
    error("C++类"..self.__name.."不允许在脚本层复制构造!")
    end

    -- lua类的初始化
    if self.copy_init then
    self.copy_init(LuaObj, ...)
    end

    self._CreateingInstance = nil
    return LuaObj
    end

    local prefix = "<class "
    local postfix = "("..tostring(NewClass)..")"..">"

    setmetatable(NewClass, {
    __index = search_base,---3
    __call = NewClass.New,
    __tostring = function(cls)
    if rawget(NewClass, "__cppclass") then
    prefix = "<class(C++) "
    end
    if NewClass.__name then
    return prefix..NewClass.__name.." "..postfix
    else
    return prefix..postfix
    end
    end
    })

    return NewClass
    end


    CActor = class()

    CActor.Init = function(self, args)
    print("cactor.init")

    --如果self中有InitModel则调用,没有则在其基类中查找
    --本例中self是由hero传来的,hero中有InitModel故调用之
    self:InitModel()

    --而hero中没有InitPart则调用基类Actor的InitPart
    --查找过程1,2,3
    self:InitPart()
    end

    CActor.InitModel = function()
    print("CActor.InitModel");
    end


    CActor.InitPart = function()
    print("CActor.InitPart");
    end

    CHero = class(CActor)

    CHero.Init = function(self, args)
    print("chero.init")
    CActor.Init(self, args)
    end

    CHero.InitModel = function()
    print("CHero.InitModel");
    CActor.InitModel()
    end


    local hero = CHero:New()

    --output:
    --~ chero.init
    --~ cactor.init
    --~ CHero.InitModel
    --~ CActor.InitModel
    --~ CActor.InitPart

     

  • 相关阅读:
    [原创]失眠应该顺其自然
    [原创]电饭锅终于煮出有粥油的小米粥了
    [原创]背诵是最好的入静法门
    JSON字符串与JSON对象的区别
    C#注解属性的感想一:
    我对面向对象的理解二:
    我对面向对象的理解一:
    如何理解泛型中的new()约束
    vue关于导航守卫的几种应用场景
    vue3中如何去请求数据
  • 原文地址:https://www.cnblogs.com/timeObjserver/p/6138345.html
Copyright © 2011-2022 走看看