lua oop[0]:实现基本的OO 框架

本文介绍了如何在Lua中实现一个简单的面向对象(OO)框架,包括创建Class函数以生成对象,以及实现继承功能。通过示例代码展示了如何使用这个框架,并讨论了在实现过程中遇到的问题,如浅复制导致的父类属性修改问题,以及解决这些问题的策略,如使用深复制和避免元表无限嵌套。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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的实现中元表是不能无限嵌套的(防止无限递归)所以下面的代码会出错

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值