上一篇记录了我使用 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. 05_Excel操作_03_模拟Web环境的Excel导入

    [思路简述] 本文继续上一篇文章,上一篇中生成了“D://用户列表.xls”的excel文件,我们接下来将这个excel导入,然后显示在控制台上. 工程什么的都同上一篇文章,只是在ExcelServi ...

  2. ZOJ 2702 Unrhymable Rhymes(DP)

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1702 题目大意:给定有很多数字组成的诗,譬如 “AABB”, “AB ...

  3. GitCam一款Gif动画制作软件

    本篇文章由:http://www.sollyu.com/gitcam-a-gif-animation-software/ 说明 GifCam是一款小巧.免费的录制电脑屏幕并制作成GIF动画的软件,具有 ...

  4. Jquery 动态生成表单 并将表单数据 批量通过Ajax插入到数据库

    利用Jquery 动态生成 Table 表单 之后利用each 方法来遍历所有文本框获取文本的value值  并通过Ajax 将数据 提交到Web服务里把数据插入数据库 Html页面 <!DOC ...

  5. git 备份和恢复

    实际应用 设置之前要在个人用户设置中增加key(为了备份ssh的项目) 备份 进入ditlab容器 cd /home/git/gitlab bundle exec rake gitlab:backup ...

  6. 关于ubuntu上执行错误命令报错

    Sorry, command-not-found has crashed! 新安装了一台ubuntu server 安装时用中文安装的,之后命令行下各种乱码,最后也不知道是修改哪里造成的 每次执行一次 ...

  7. u-boot和linux的机器码

    先看u-boot的机器码和linux的机器码是在什么地方决定的. 1. u-boot的机器码是在u-boot的board/fs2410/fs2410.c文件里决定的:     /* arch numb ...

  8. wap开发之滑动事件(swipe、tap、swipeleft、swiperight)等

    最近一直找在wap端可以实现的swipe等滑动事件的方法,开始研究了jquery-mobile,zepto,结果由于jqm太大.zepto有不少缺陷.为此研究了zepto,想把里面的swipe事件独立 ...

  9. docker的基本使用

    docker 基本的使用命令docker pull centos:latestdocker images centosdocker run -i -t centos /bin/bash //也可以使用 ...

  10. shell for循环+case的脚本(监控程序状态)

    分享一个shell for循环+case的脚本(监控程序状态) 分享一个for循环+case的脚本(监控程序状态并执行相关操作) ,供大家学习参考. 复制代码代码如下: #/bin/bash set ...