上一篇记录了我使用 Slua.Class 来实现面向对象扩展 C# 中得类,但实际使用中,更多地情况是直接在 lua 中定义基类然后扩展,于是触发了我重新思考下是否两种形式应该统一用一种,目前的方案中,有一个不好的地方是,每一个派生类的实例,其实内部会有多个实例(每一个继承的类都有个对应的实例,参考 __call 的调用),所以继承层次越深,内部的实例越多,而这些父类的实例仅仅是提供了属性和方法而已,没有其它作用,这其实造成了一种浪费,但如果改动的话,我想整个结构和基础都得该,影响了本身 slua 中代码的兼容性。

  我仔细阅读了云风给出的 lua oop 方案,方法够精简,确实也解决了我想解决的问题,所有的类对象,都只有一个实例,他们查询父类的方法和属性,都通过缓存的 table 来查询,避免了浪费。但对于我个人目前的需求来讲,还有些不足:

  1. 包装的过于严实,无法直接使用 类名.静态方法名 来使用静态方法;
  2. 无法直接使用 super 关键字来访问父类方法,这样只能强制你完全重写继承的方法;(而关于我修改的 slua 中的 通过 __base 访问父类的机制,其实有缺陷,因为 只能通过 self.__base.Method(self, ...),但是 super 应该隶属于类而不是对象,应该 NewCls.__base.Method(self, ...) 这样才对。),修改完应该每个派生类会多一个实例用来指向 super 的父类访问,而这个类是共享的,所以开销可以忽略不计;
  3. 为了整体代码风格统一(提供同 Slua.Class 继承类同样的实例化类方法),我需要也添加一个默认实例化方法: local obj = NewCls(...),等同于 local obj = NewCls.new(...)。

  修改完的代码如下(请忽略我修改了变量名):

-- The hold all class type.
local __TxClassTypeList = {} -- The inherit class function.
local function TxClass(SuperType)
-- Create new class type.
local ClassType = {}
ClassType.Ctor = false
ClassType.SuperType = SuperType -- Create new class instance function.
local function ClassTypeInstance(...)
local Obj = {}
do
local Create
Create = function (c, ...)
if c.SuperType then
Create(c.SuperType, ...)
end if c.Ctor then
c.Ctor(Obj, ...)
end
end Create(ClassType, ...)
end setmetatable(Obj, {__index = __TxClassTypeList[ClassType]})
return Obj
end -- The new function of this class.
ClassType.new = ClassTypeInstance -- The super class type of this class.
if SuperType then
ClassType.super = setmetatable({},
{
__index = function (t, k)
local Func = __TxClassTypeList[SuperType][k]
if "function" == type(Func) then
t[k] = Func
return Func
else
error("Accessing super class field are not allowed!")
end
end
})
end -- Virtual table
local Vtbl = {}
__TxClassTypeList[ClassType] = Vtbl -- Set index and new index of ClassType, and provide a default create method.
setmetatable(ClassType,
{
__index = function (t, k)
return Vtbl[k]
end, __newindex = function (t, k, v)
Vtbl[k] = v
end, __call = function (self, ...)
return ClassTypeInstance(...)
end
}) -- To copy super class things that this class not have.
if SuperType then
setmetatable(Vtbl,
{
__index = function (t, k)
local Ret = __TxClassTypeList[SuperType][k]
Vtbl[k] = Ret
return Ret
end
})
end return ClassType
end

  现在我可以如下使用:

-- Base class.
local BaseFoo = TxClass() BaseFoo.Name = "I am BaseFoo!" function BaseFoo:Ctor()
print("BaseFoo in constructor.")
end function BaseFoo.PrintHello()
print("Hello BaseFoo!")
end function BaseFoo:Foo()
print("Name is: " .. self.Name)
end -- Derived class.
local MyFoo = TxClass(BaseFoo) MyFoo.Age = function MyFoo:Ctor()
print("MyFoo in constructor.")
end function MyFoo:Foo()
MyFoo.super.Foo(self)
print("Age is: " .. tostring(self.Age))
end -- Create instance.
local bf = BaseFoo.new()
bf:Foo() local mf = MyFoo()
mf:Foo() BaseFoo.PrintHello()
MyFoo.PrintHello()

  接下来如云风所说,我应该思考下如何实现 Destructor。

 

在 slua 中使用更新的面向对象方案的更多相关文章

  1. SLua 中使用 Lua 5.3 的编译工程

    2016-03-05 更新: 之前编译的库,在 Android 下 Lua_Number 和 Lua_Integer 被编译为了32位,导致从 C# 到 Lua 过程中有64位到32位整型转换会出现溢 ...

  2. PostgreSQL中实现更新默认值(二)

    今天我们用表继承+触发器的方案,来实现表中的更新默认值.这也许是PostgreSQL里最佳的解决方案. 一. 创建一张表,作为父表 create table basic_update( t_updat ...

  3. C#多线程开发中如何更新UI界面控件内容

    子线程不能修改UI线程的状态(比如文本框里面的内容). 解决的办法是写一个用来更新文本框内容的函数,然后在Worker线程里面通过BeginInvoke来利用delegate调用这个函数更新文本框. ...

  4. Android中动态更新ListView(转)

    在使用ListView时,会遇到当ListView列表滑动到最底端时,添加新的列表项的问题,本文通过代码演示如何动态的添加新的列表项到ListView中.实现步骤:调用ListView的setOnSc ...

  5. web.config中sessionState节点的配置方案

    web.config中sessionState节点的配置方案 web.config关于sessionState节点的配置方案,sessionState有五种模式:Custom,off,inProc,S ...

  6. Spark小课堂Week7 从Spark中一个例子看面向对象设计

    Spark小课堂Week7 从Spark中一个例子看面向对象设计 今天我们讨论了个问题,来设计一个Spark中的常用功能. 功能描述:数据源是一切处理的源头,这次要实现下加载数据源的方法load() ...

  7. slua 中使用 lua5.3

    因为我们服务器极有可能要迁移到 skynet 上,它基于 lua5.3,而服务器和客户端会公用很多lua代码,所以在考虑在客户端 slua 中使用 lua5.3. 经过编译后,发现 slua 对 lu ...

  8. WPF中动态更新TextBlock文字中的超链接,文本

    1.------------------------------------------------------------------------- 修改超链接的文本文字: <TextBloc ...

  9. echarts异步数据加载(在下拉框选择事件中异步更新数据)

    接触echarts 大半年了,从不会到熟练也做过不少的图表,隔了一段时间没使用这玩意,好多东西真心容易忘了.在接触echarts这期间也没有总结什么东西,今天我就来总结一下如何在echart中异步加载 ...

随机推荐

  1. poj2104:K-th Number

    思路:可持久化线段树,利用权值线段树,把建树过程看成插入,插入第i个元素就在第i-1棵树的基础上新建结点然后得到第i棵树,那么询问区间[l,r]就是第r棵树上的信息对应减去第l-1棵树上的信息,然后再 ...

  2. 使用SqlBulkCopy批量插入多条数据进入表中

    由于工作中项目需求结算一次生成一批相同批次号的数据插入一个表中,然后再通过另一页面展示出来,所以需要用到一次性插入一批数据,所以就采用了SqlBulkCopy插入一批数据 1 public stati ...

  3. Python中dict详解

    from:http://www.cnblogs.com/yangyongzhi/archive/2012/09/17/2688326.html Python中dict详解 python3.0以上,pr ...

  4. fork();

    僵死进程: 父进程没有等待子进程,wait() 子进程会变成僵死进程. int main(int arg, char *args[]){ pid_t pid = fork();//调用fork产生一个 ...

  5. java中的多线程——进度1

    import java.util.*;public static void main(String[] args) {/*final可以修饰类,方法,变量.final修饰的类不可以被继承.final修 ...

  6. workerman安装

    1.workerman安装 workerman是php的一个socket框架,简化了socket编程,已经为很多企业所用,今天在centos的ngix+php下安装了workerman,过程记录如下. ...

  7. php实现手机拍照上传头像功能

    现在手机拍照很火,那么如何使用手机拍照并上传头像呢?原因很简单,就是数据传递,首先手机传递照片信息,这个就不是post传递 也不是get函数传递, 这个另外一种数据格式传递,使用的是$GLOBALS ...

  8. PHP图片上传程序(完整版)

    从PHP100上搜刮来的,功能很强大.几乎考虑到了每个细节,与大家分享!~~~ <meta http-equiv="Content-Type" content="t ...

  9. Python Tips and Traps(一)

    1.如果想得到一个列表的index和内容,可以通过enumerate快速实现 drinks = ['coffee','tea', 'milk', 'water'] for index, drink i ...

  10. vs2013 IHttpActionResult NotFund Ok (WebAPI)

    vs2013  IHttpActionResult NotFund Ok   使用ASP.NET Web API构造基于restful风格web services,IHttpActionResult是 ...