luaoop | 实现基本的OO 框架

Posted 自科部

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luaoop | 实现基本的OO 框架相关的知识,希望对你有一定的参考价值。

lua虽然原生面向对象,不过它提供了一些功能,使得我们很容易模拟出对象

云风以前也实现过一次,代码有点复杂,我想重新实现一些。

目标

实现一个Class 函数,它接收一个构造函数,然后返回一个生成器,每次调用这个生成器可以生成一个新的对象。

具体用法如下:

  
package.path=package.path..";./code/luagy/?.lua;./luagy/?.lua"
Class=require("grammar.class")

baseclass=Class(function (self,x) --构造函数
   self.x=x
   print ("baseclass init ")
   self:fn(x)
 end
)

baseclass.level=1 --属性
function baseclass:fn(x) --方法
 print("call baseclass fn")
 self.x=x
end

baseobj1=baseclass(1) --新建对象
baseobj2=baseclass(2)

print(baseobj1.x,baseobj2.x)
baseobj2:fn(3)
print(baseobj1.x,baseobj2.x)

baseobj1.level=3

print(baseclass.level,baseobj2.level,baseobj1.level)

实现

用了十多行实现了基本的功能:

  
local function Class( _ctor)
 local c = {} --生成器
 c.__index = c  --对象要从类索引方法等
 c._ctor = _ctor --保留构造函数
 
 setmetatable(c, {__call = function(class_tbl, ...)
   local obj = {} --新的对象
   setmetatable(obj,c)
   
   if c._ctor then
     c._ctor(obj,...)
   end
   return obj
 end})
 return c
end

return Class

继承

下面来实现关于的类的继承

目标是实现类似下面的调用

  
childclass1=Class(baseclass,function (self,y)
   self.y=y
end)

co1=childclass1(3)
co1:fn(2)

print(co1.x,co1.y,co1.level)

只要把Class 函数的参数改成两个,如果第一个参数类型是函数的话,说明它是一个基类,不用从父类复制方法和属性,相反,如果是table,就复制父类的所有属性的方法到子类,然后用第二个参数构造生成器。

这也就是为什么Class返回的是table而不是函数的原因之一

具体如下:

  
local function Class(base, _ctor)
 local c = {} --生成器
 
 if not _ctor and type(base) == 'function' then
   --基类
   _ctor = base
   base = nil
   
 elseif type(base) == 'table' then
 
   --复制父类的方法
   for i,v in pairs(base) do
     c[i] = v
   end
   
   c._base = base
 end
 
 
 c.__index = c  --对象要从类索引方法等
 c._ctor = _ctor --保留构造函数
 
 setmetatable(c, {__call = function(class_tbl, ...)
   local obj = {} --新的对象
   setmetatable(obj,c)
   
   if c._ctor then
     c._ctor(obj,...)
   end
   return obj
 end})
 return c
end

return Class

这样一个基本的 OO框架就完成了,不过还有许多的问题。首先,在从父类复制属性时,是利用浅复制,假如属性的类型是table,修改子类的该属性,父类的也会跟着改变。或者可以这样解决:

  • 对于特殊的类型(如table) 递归复制,直到所有变量都为基本类型为止,但是有些类型(userdata)并不能进行深复制,要有对应的复制函数

  • 将属性的定义放在一个特殊的函数里,每次构造新对象重新生成属性,这样的代码基本上不用改动,问题就得到解决

由于每一次新建一个类时,父类的构造函数被重载了,所以要调用父类的构造函数只能这样

  

cc2=Class(baseclass,function (self)
   self._base._ctor(self)
   ...
end)

还有,因为使用了元表,但是lua的实现中元表是不能无限嵌套的(防止无限递归)所以下面的代码会出错


以上是关于luaoop | 实现基本的OO 框架的主要内容,如果未能解决你的问题,请参考以下文章

第六章.解决大问题

oo第三单元总结

OO第三单元总结

OO-第三单元总结-2021

Scala的面向对象与函数编程

html PHP代码片段: - AJAX基本示例:此代码演示了使用PHP和JavaScript实现的基本AJAX功能。