关于云风在 Lua 中实现面向对象的源码分析

来源:互联网 发布:上海和数软件 编辑:程序博客网 时间:2024/06/04 19:27

①源码:

local _class={} function class(super)local class_type={}class_type.ctor=falseclass_type.super=superclass_type.new=function(...) local obj={}dolocal createcreate = function(c,...)if c.super thencreate(c.super,...)endif c.ctor thenc.ctor(obj,...)endend create(class_type,...)endsetmetatable(obj,{ __index=_class[class_type] })return objendlocal vtbl={}_class[class_type]=vtbl setmetatable(class_type,{__newindex=function(t,k,v)vtbl[k]=vend}) if super thensetmetatable(vtbl,{__index=function(t,k)local ret=_class[super][k]vtbl[k]=retreturn retend})end return class_typeend

②使用示例:

现在,我们来看看怎么使用:

base_type=class()-- 定义一个基类 base_type function base_type:ctor(x)-- 定义 base_type 的构造函数print("base_type ctor")self.x=xend function base_type:print_x()-- 定义一个成员函数 base_type:print_xprint(self.x)end function base_type:hello()-- 定义另一个成员函数 base_type:helloprint("hello base_type")end

以上是基本的 class 定义的语法,完全兼容 lua 的编程习惯。我增加了一个叫做 ctor 的词,作为构造函数的名字。
下面看看怎样继承:
test=class(base_type)-- 定义一个类 test 继承于 base_type function test:ctor()-- 定义 test 的构造函数print("test ctor")end function test:hello()-- 重载 base_type:hello 为 test:helloprint("hello test")end

现在可以试一下了:
a=test.new(1)-- 输出两行,base_type ctor 和 test ctor 。这个对象被正确的构造了。a:print_x()-- 输出 1 ,这个是基类 base_type 中的成员函数。a:hello()-- 输出 hello test ,这个函数被重载了。

③原理分析

① 通过引入_class来索引各个类(class_type)的对应的vtbl(里面记录了该类的成员变量和成员方法,通过__newindex原方法来实现,拦截对class_type元素的直接赋值转而保存在对应的vtbl表中);


② 允许用户通过重写class_typector函数来自定义构造过程(主要用于实现成员变量的定义),开放唯一一个实例化函数来让用户生成对象实例(该函数的主要任务是递归调用上层类的ctor函数,并把要返回的对象实例的__index设置为该class_type对应的vtbl)。所以class_type在整个过程中只是只是实现了把对象实例跟vtbl表绑定的任务;


③ 最后,如果该类有父类,就把它的vtbl__index元方法设置为父类的__index。那么最后呈现出来的结果就是对象实例的__index指向该类对应的vtbl,然后它再指向更上层父类对应的vtbl。任何对类的赋值都被__newindex拦截,从而转为向对应的vtbl赋值。


0 0