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

LUA类的更多相关文章

  1. lua 类支持属性不能被修改

    背景 lua是类是借助表的来实现的, 类被定义后, 在使用场景下, 不希望被修改.如果被修改, 则影响的类的原始定义, 影响所有使用类的地方. 例如: --- router.lua class fil ...

  2. Lua类的继承 参考实现

    参考url: https://blog.codingnow.com/cloud/LuaOO 最近在思考lua类的继承实现 ,参考了云风的类实现,感觉他的更像是接口写法.于是尝试用自己的方式重写了类实例 ...

  3. Lua类和类继承实现

    Lua本身是不能像C++那样直接实现继承,但我们可以用万能的table表来实现. 以下我总结了三种方式的类以及继承的实现 第一.官方的做法,使用元表实现 原理参照<Programming in ...

  4. lua 类实现

    Class={}; Class.classList={}; --保存所有已经定义过的类 --类的类型: 类和接口, 接口也是一种类 Class.TYPE_CLASS="Class" ...

  5. <7>Lua类的表的实例创建

    根据上一节知识所述Lua中没有像C.C++.JAVA中的类概念,面向对象等 ,但我们可以模拟出来 如下 代码如下: --创建类的表 local Person = {} function Person: ...

  6. lua类实现

    _Account = {} --创建一张借记卡 function _Account:new( tb ) local _Tb = tb or {} setmetatable(_Tb, self) sel ...

  7. lua 类继承和实现

    http://blog.csdn.net/ssihc0/article/details/7742323 Account={balance=}; --新建了一个对像,他有一个属性balance func ...

  8. lua 面向对象编程类机制实现

    lua no class It is a prototype based language. 在此语言中没有class关键字来创建类. 现代ES6, 已经添加class类. prototype bas ...

  9. 【Quick-COCOS2D-X 3.3 怎样绑定自己定义类至Lua之三】动手绑定自己定义类至Lua

        查看[Quick-COCOS2D-X 3.3 怎样绑定自己定义类至Lua之二]新建项目中配制环境,我们完美的在新建项目中完毕了绑定须要的环境,接下来才是最关健的一步.绑定自己定义C++类至Lu ...

随机推荐

  1. Redis安装配置

    Redis有服务端和客户端 服务端: 服务端下载地址: https://github.com/dmajkic/redis/downloads 解压后: 然后进入CMD命令: 不要关闭此命令窗(关闭服务 ...

  2. 《Effective C#》读书笔记

    Effiective C# Item1 : 使用属性代替成员变量 Effective C# Item2:运行时常量(readonly)优于编译时常量(const) Effective C# Item3 ...

  3. 【JavaScript】获取未知类的结构

    目录结构: // contents structure [-] 为什么需要获取类的结构 关于JavaScript中的类 定义类的方法 第一种 第二种 DEMO HTML页面 date文件 注意事项 参 ...

  4. [JS]笔记15之客户端存储cookie

    -->本地存储发展情况 -->什么是cookie -->cookie优缺点 -->cookie的设置.读取.删除 -->cookie应用 本地存储发展情况 一.什么是co ...

  5. How To Collect ULS Log from SharePoint Farm

    We can use below command to collect SharePoint ULS log from all servers in the Farm in PowerShell. M ...

  6. Android开发—已root的手机获取data路径

    开发android的时候,尽管手机已经root但是DDMS中还是没有data/data路径怎么办? 可以用cmd命令提示符为逐个文件夹设置权限: 打开cmd,输入 adb shell  回车—> ...

  7. html之file标签 --- 图片上传前预览 -- FileReader

    记得以前做网站时,曾经需要实现一个图片上传到服务器前,先预览的功能.当时用html的<input type="file"/>标签一直实现不了,最后舍弃了这个标签,使用了 ...

  8. Android 自定义线程池的实战

    前言:在上一篇文章中我们讲到了AsyncTask的基本使用.AsyncTask的封装.AsyncTask 的串行/并行线程队列.自定义线程池.线程池的快速创建方式. 对线程池不了解的同学可以先看 An ...

  9. iPad编程

    1. iPad 现有型号: iPad Pro, iPad Air, iPad mini 均配备Retina显示屏.早期还有iPad 依次对应的坐标系及分辨率: iPad Pro 坐标系:1366 x ...

  10. SQL SERVER 2012 从Enterprise Evaluation Edtion 升级到 Standard Edtion SP1

    案例背景:公司从意大利购买了一套中控系统,前期我也没有参与其中(包括安装.实施都是第三方),直到最近项目负责人告诉我:前期谈判以为是数据库的License费用包含在合同中,现在经过确认SQL Serv ...