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. 用好spring mvc validator可以简化代码

    表单的数据检验对一个程序来讲非常重要,因为对于客户端的数据不能完全信任,常规的检验类型有: 参数为空,根据不同的业务规定要求表单项是必填项 参数值的有效性,比如产品的价格,一定不能是负数 多个表单项组 ...

  2. tomcat 自定义classpath(亲自测试)

    因为一直以来使用tomcat和weblogic作为应用服务器为主,最近在升级新中间件的过程中遇到一个问题,我们的web前端应用现在升级是进行全量包升级的,因为现在的系统架构为前端和后端通过rpc框架交 ...

  3. jquery动态改变div宽度和高度

    效果体验:http://keleyi.com/keleyi/phtml/jquery/23.htm 完整代码: <!DOCTYPE html PUBLIC "-//W3C//DTD X ...

  4. JS高程3.基本概念(3)

    1.ECMAScript数值的范围 由于内存的限制,在大多数浏览器中,ECMAScript能够拿保存的数据的范围是 5e-324 ~ 1.7976931348623157e+308,其中最小的数值保存 ...

  5. react引用ant的table组件

    import React from 'react';import '../../css/uicss/UI.css';import 'antd/lib/style/index.less';import ...

  6. placeholder不兼容 IE10 以下版本的解决方法

    对于密码输入框placeholder的兼容问题:HTML代码:<input type="password" id="loginPassword" plac ...

  7. Bootstrap之栅格系统

    bootstrap 移动优先 中文官网  http://www.bootcss.com/ 1.基本模板 <!DOCTYPE html> <html lang="en&quo ...

  8. jQuery实用小技巧--输入框文字获取和失去焦点

    <input id="txt" class="text1"  type="text" />   <script src=& ...

  9. 多人开发Xcode工程冲突,打不开解决办法

    在公司多人协作开发,相信好多程序员都遇到非常忧伤的问题,就是工程打不开,这样就无从下手,好多程序怨只能再从代码服务器上下载一份新的代码,今天军哥教你几个小技巧,让你的bigger瞬间提升一个档次 在公 ...

  10. [Erlang 0106] Erlang实现Apple Push Notifications消息推送

        我们的IOS移动应用要实现消息推送,告诉用户有多少条消息未读,类似下图的效果(笑果),特把APNS和Erlang相关解决方案笔记于此备忘.          上面图片中是Apple Notif ...