Lua:面向对象,多态,重载,私有,单例

2023-08-24 15:14:02 浏览数 (2)

面向对象

代码语言:javascript复制
--保存类类型的虚表
local _class = {}
 
-- added by wsh @ 2017-12-09
-- 自定义类型
ClassType = {
   class = 1,
   instance = 2,
}
 
function BaseClass(classname, super)
   assert(type(classname) == "string" and #classname > 0)
   -- 生成一个类类型
   local class_type = {}
   
   -- 在创建对象的时候自动调用
   class_type.__init = false
   class_type.__delete = false
   class_type.__cname = classname
   class_type.__ctype = ClassType.class
   
   class_type.super = super
   class_type.New = function(...)
      -- 生成一个类对象
      local obj = {}
      obj._class_type = class_type
      obj.__ctype = ClassType.instance
      
      -- 在初始化之前注册基类方法
      setmetatable(obj, { 
         __index = _class[class_type],
      })
      -- 调用初始化方法
      do
         local create
         create = function(c, ...)
            if c.super then
               create(c.super, ...)
            end
            if c.__init then
               c.__init(obj, ...)
            end
         end

         create(class_type, ...)
      end

      -- 注册一个delete方法
      obj.Delete = function(self)
         local now_super = self._class_type 
         while now_super ~= nil do  
            if now_super.__delete then
               now_super.__delete(self)
            end
            now_super = now_super.super
         end
      end

      return obj
   end

   local vtbl = {}
   -- added by wsh @ 2017-12-08
   assert(_class[class_type] == nil, "Aready defined class : ", classname)
   _class[class_type] = vtbl
 
   setmetatable(class_type, {
      __newindex = function(t,k,v)
         vtbl[k] = v
      end
      , 
      --For call parent method
      __index = vtbl,
   })
 
   if super then
      setmetatable(vtbl, {
         __index = function(t,k)
            local ret = _class[super][k]
            --do not do accept, make hot update work right!
            --vtbl[k] = ret
            return ret
         end
      })
   end
 
   return class_type
end


BaseView = BaseView or BaseClass("BaseView")

BaseView.a = 1
BaseView.b = 2

function BaseView:__init()
	print("BaseView:__init")
end

function BaseView:__delete()
	print("BaseView:__delete")
end

function BaseView:DoBaseFunc()
	print("BaseView:DoBaseFunc")
end

function BaseView:DoSomething()
	print("BaseView:DoSomething")
end

LoginView = LoginView or BaseClass("LoginView",BaseView)


function LoginView:__init()
	print("LoginView:__init")
end

function LoginView:__delete()
	print("LoginView:__delete")
end

function LoginView:DoSomething()
	print("LoginView:DoSomething")
end

ologin_view = LoginView:New() -->BaseView:__init   LoginView:__init
ologin_view:Delete()  -->LoginView:__delete   BaseView:__delete

print(ologin_view.a) -->1
ologin_view.a = 3
print(ologin_view.a) -->3
ologin_view.c = 4
print(ologin_view.c) -->4
print(BaseView.c) -->nil
print(ologin_view:DoBaseFunc()) -->BaseView:DoBaseFunc
print(ologin_view:DoSomething()) -->LoginView:DoSomething

访问基类成员方法

代码语言:javascript复制
local function OnCreate(self)
	self._class_type.super.OnCreate(self)
end

多态

子类直接写新函数名,覆盖父类

重载

代码语言:javascript复制
-- 添加组件
-- 多种重载方式
-- 1、直接添加Lua侧组件:inst:AddComponent(ComponentTypeClass, luaComponentInst)
-- 2、指定Lua侧组件类型和必要参数,新建组件并添加,多种重载方式:
--    A)inst:AddComponent(ComponentTypeClass, relative_path)
--    B)inst:AddComponent(ComponentTypeClass, child_index)
--    C)inst:AddComponent(ComponentTypeClass, unity_gameObject)
local function AddComponent(self, component_target, var_arg, ...)
   assert(component_target.__ctype == ClassType.class)
   local component_inst = nil
   local component_class = nil
   if type(var_arg) == "table" and var_arg.__ctype == ClassType.instance then
      component_inst = var_arg
      component_class = var_arg._class_type
   else
      component_inst = component_target.New(self, var_arg)
      component_class = component_target
      component_inst:OnCreate(...)
   end
   
   local name = component_inst:GetName()
   AddNewRecordIfNeeded(self, name)
   RecordComponent(self, name, component_class, component_inst)
   self.length = self.length   1
   return component_inst
end

通过type 确定不同类型,进行访问

保护级别

Lua里面可以做到脚本级别的成员保护,分为:私有成员、公有成员。私有成员就是在脚本全局范围内定义的局部变量,而对于表来说,所有成员都是公有的。 A) 数据成员 私有数据成员,直接在脚本中local定义就行,如上面的基类base赋值语句,这个base就不能在其它脚本被访问到。 公有数据成员,需要写入虚表(对表进行赋值),使用self.xxx就行。 B) 成员函数 私有成员函数:目前的类定义,所有的函数我都是使用local定义的,使用local定义的function如果不写入虚表,那它就是私有的,这点和数据成员一样。 公有成员函数:如果想暴露某个成员函数成为公有函数,只需要在类定义底部写入虚表即可。 例如:

代码语言:javascript复制
UIBaseContainer.OnCreate = OnCreate
UIBaseContainer.OnEnable = OnEnable
UIBaseContainer.Walk = Walk
UIBaseContainer.OnComponentSetName = OnComponentSetName
UIBaseContainer.OnComponentDestroy = OnComponentDestroy
UIBaseContainer.AddComponent = AddComponent
UIBaseContainer.GetComponent = GetComponent
UIBaseContainer.GetComponents = GetComponents
UIBaseContainer.GetComponentsCount = GetComponentsCount
UIBaseContainer.RemoveComponent = RemoveComponent
UIBaseContainer.RemoveComponents = RemoveComponents
UIBaseContainer.OnDisable = OnDisable
UIBaseContainer.OnDestroy = OnDestroy

return UIBaseContainer

单例

c#单例 使用GetInstance访问,每次只返回 唯一的new 的table

代码语言:javascript复制
local function __init(self)
   assert(rawget(self._class_type, "Instance") == nil, self._class_type.__cname.." to create singleton twice!")
   rawset(self._class_type, "Instance", self)
end

local function __delete(self)
   rawset(self._class_type, "Instance", nil)
end

local function GetInstance(self)
   if rawget(self, "Instance") == nil then
      rawset(self, "Instance", self.New())
   end
   assert(self.Instance ~= nil)
   return self.Instance
end

0 人点赞