上一篇记录了我使用 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操作_01_简单导入导出

    [Excel组成] 主要由四部分组成: 1.工作簿 每一个Excel文件都可以看成是一个工作簿,当打开一个Excel文件时,相当于打开了一个Excel工作簿. 2.工作表 当打开了Excel工作簿后, ...

  2. 【BZOJ3884】【降幂大法】上帝与集合的正确用法

    Description 根据一些书上的记载,上帝的一次失败的创世经历是这样的: 第一天, 上帝创造了一个世界的基本元素,称做“元”. 第二天, 上帝创造了一个新的元素,称作“α”.“α”被定义为“元” ...

  3. 九度OJ 1433 FatMouse -- 贪心算法

    题目地址:http://ac.jobdu.com/problem.php?pid=1433 题目描述: FatMouse prepared M pounds of cat food, ready to ...

  4. 桥接模式(Bridge Pattern)

    桥接模式,用于将抽象化与实现化解偶,使得二者可以独立变化. 举一个数据库JDBC的例子: 定义一个Driver接口,不同的数据库实现的接口,如MySQL,SQLServer public interf ...

  5. Linux命令——监视相关

    1.netstat 用于显示各种网络相关信息,如网络连接,路由表,接口状态 (Interface Statistics),masquerade 连接,多播成员 (Multicast Membershi ...

  6. Wap站总结一

    前段时间负责了公司的wap站前端工作,目前wap站的基础及较为复杂的几张页面都已经出来,现根据自己的一些经验,贴出部分心得,希望对现在或者以后可能会接触到Wap站的一些人有些帮助 一.本次WAP网站的 ...

  7. jquery禁用a标签,jquery禁用按钮click点击

    jquery禁用a标签方法1 $(document).ready(function () { $("a").each(function () { var textValue = $ ...

  8. php单引号和双引号的区别与用法

    php里的单引号把内容当成纯文本,不会经过服务器翻译.而双引号则与此相反.里面的内容会经过服务器处理(process). 举个简单的例子:   $foo="data"; echo ...

  9. win7的IE11降到IE8

    我为什么要降低IE版本呢?...... 下载了抓包工具HttpWatch,下载地址http://pan.baidu.com/s/1kVhPMmj  版本如下: 用IE11打开抓包时流内没有内容,可能跟 ...

  10. FastCgi与PHP-fpm关系[转] 读完本文瞬间明朗了很多

    刚开始对这个问题我也挺纠结的,看了<HTTP权威指南>后,感觉清晰了不少. 首先,CGI是干嘛的?CGI是为了保证web server传递过来的数据是标准格式的,方便CGI程序的编写者. ...