Lua面向对象

metatable的介绍:

Lua的table可以模拟面向对象,都得益于metatable的强大之处。在一个table中,如果索引一个元素未能找到,解释器会去该table下的metatable中的__index元素中去寻找,即table.metatable.__index.xxx中寻找。

但是如果要修改table中的元素或赋值操作,但是该元素不存在,那么会在table中创建该元素,而不会去metatable.__index中寻找。

类创建方法的实现方式:

--function.lua

--clone function
function Clone(object)
    local lookup_table = {}
    local function _copy(object)
        if type(object) ~= "table" then
            return object
        elseif lookup_table[object] then
            return lookup_table[object]
        end
        local new_table = {}
        lookup_table[object] = new_table
        for key, value in pairs(object) do
            new_table[_copy(key)] = _copy(value)
        end
        return setmetatable(new_table, getmetatable(object))
    end
    return _copy(object)
end

--class create
class = function (classname, super)
    local cls
    -- inherited from Lua Object
    if super then
        cls = Clone(super)
        cls.super = super
        if not cls.Ctor then
            cls.Ctor = function() end
        end
    else
        cls = {Ctor = function() end}
    end

    cls.__cname = classname
    cls.__ctype = 2 -- lua
    cls.__index = cls

    function cls.New(...)
        local instance = setmetatable({}, cls)
        instance:Ctor(...)
        return instance
    end
    return cls
end

分析:

1.class方法中两个参数,classname代表的是要创建的类的类名,super代表所创建类的基类。首先class判断是否有supper,如果没有基类,会为本类创建空的构造方法。如果有基类,则调用Clone方法来克隆基类,这里Clone方法会把基类的成员函数映射到派生类里面去。

2.New方法实现:这里会把构造出来的类的实例instance的元表设定成类table自身,并且由于类table自身的__index参数还是类table自身。instance中没有任何成员函数,用instance调用成员函数的时候,本是找不到函数的,但是因为instance里面的元表(metatable)存在即指挥类自身,并且类自身里面还有__index。所以还会去类自身table中的__index中搜索,此时__index还是指向自身,所以自身的成员方法就能找到了。

3.类自身只放成员方法,不能放成员变量,原因如下:

a.由于metatable的原理,即只有读的时候会去metatable中找,写的时候如果instance中没有,不会去索引metatable而是在instance中新增一个。

b.由于继承时候,Ctor构造方法的直接调用者是instance,所以各级构造方法构造的变量都会放到instance中,而非类自身table里。

Lua多实例(一个类可以获取多个类的对象)基类实现:

--object.lua
local Object = class("Object")
return Object

使用方法:

--multi.lua
local Object = require "object"
local Multi = class("Multi", Object)

function Multi:Ctor(...)
    --super constructor
    Object.Ctor(self)
    --class memebers constructor
    self.m_mem = 0
end
function Multi:Show()
    print(self.m_mem)
end
local instance1 = Multi:New()
instance1:Show()
local instance2 = Multi:New()
instance2:Show()

第一步:用class方法创建multi类继承于Object类。

第二步:派生类multi中的构造方法是Object.Ctor的引用,所以要重新写派生类multi的构造方法。multi类Ctor构造multi的数据时候,首先要在multi中构造父类的数据,所以要在派生类的Ctor中先调用父类的Ctor。这里必须使用Object.Ctor(self),不能使用Object:Ctor。原理是这样的:调用起源是New方法中instance:Ctor,Object.Ctor(self)是在instance:Ctor中调用的,所以这里的self则是instance。如果写成Object:Ctor,则以后的Ctor参数则变成Object,这样父级的构造方法构造的数据就放不到instance中了。总体来说由于调用Ctor的调用者是instance,所以之后派生链上的所有Ctor方法的参数都是instance,即派生类的实例。

第三步:在super.Ctor调用之后构造派生类的成员变量,即self.m_mem = 0这一行。

第四步:定义multi类的方法Show,注意所有成员方法中的self也是instance,因为外部调用成员方法是用instance:func()的。

总结:类中的所有成员方法,包括Ctor方法和普通方法,调用者都是instance,即类的对象。self自然也是instance而非multi自身。

Lua单实例类(即一个类只能初始化一个对象)的实现:

--singleton.lua
local Object  = require "object"
local Singleton = class("Singleton",Object)

function Singleton:GetSingleton(...)
    if self._instance == nil then
	self._instance = self.New(...)
    end
    return self._instance
end 

return Singleton    	

分析:此处Singleton为单实例的最高基类,该类中添加的GetSingleton方法的实质作用是在所有以Singleton为基类的方法中都用该方法获取实例(第一次获取则初始化实例),而不用New方法。此方法的调用者是Singleton或派生类本身,所以传入的self也是Singleton或派生类本体,这时要在类本体中添加一个_instance的变量,并调用New来获取一个实例放在此变量中,这便是唯一的实例。

使用方法:

--single.lua
local Singleton = require "singleton"
local Single = class("Single", Singleton)

function Single:Ctor(...)
    --super constructor
    Singleton.Ctor(self)
    --class memebers constructor
    self.m_mem = 0
end
function Single:Show()
    print(self.m_mem)
end
local instance = Single:GetSingleton()
instance:Show()

派生类的重写构造方法是一样的,初始化实例的时候要用GetSingleton方法而非New方法。

图像解析两种基类的内存表示:

         

时间: 2024-10-11 18:34:58

Lua面向对象的相关文章

Lua程序设计之————Lua面向对象2

----------------------------------------------------------- Lua面向对象3 local smartMan = { name = "Tinywan", age = 26, money = 800000, sayHello = function() print("Tinywan say 大家好") end } local t1 = {} local mt = { __index = smartMan, __n

Lua面向对象----类、继承、多继承、单例的实现

(本文转载)学习之用,侵权立删! 原文地址   http://blog.csdn.net/y_23k_bug/article/details/19965877?utm_source=tuicool&utm_medium=referral lua面向对象实现: 一个类就像是一个创建对象的模具.有些面向对象语言提供了类的概念,在这些语言中每个对象都是某个特定类的实例.lua则没有类的概念,每个对象只能自定义行为和形态.不过,要在lua中模拟类也并不困难. lua中,面向对象是用元表这个机制来实现.

Lua程序设计之————Lua面向对象1

完整代码 local mt = {} mt.__add = function(t1,t2) print("两个Table 相加的时候会调用我") end local t1 = {} local t2 = {} -- 给两个table 设置新的元表,一个元表就是一个table的值 setmetatable(t1,mt) -- meta:元素 setmetatable(t2,mt) -- 进行相加操作 local t = t1 + t2 print(t) --[[输出结果 两个Table

让lua面向对象--lua和android

让lua面向对象 lua本身不支持面向对象的特性,但是由于lua是基于原型(prototype)的语言,要实现面向对象的特性也是有一定的方法的,实现方式有很多种, 总结了一下我最近对使用lua实现面向对象的特性,主要可以分为以下两种不同的方式来实现: 1.使用metatable的__index域实现,实现的时候需要利用的lua语言的一些特性才可以实现,主要有: a.将table b作为table a的一个prototype的方法:setmetatable(a, {__index = b}); b

lua面向对象实现(实例化对象、继承、多态、多继承、单例模式)

lua面向对象实现: 一个类就像是一个创建对象的模具.有些面向对象语言提供了类的概念,在这些语言中每个对象都是某个特定类的实例.lua则没有类的概念,每个对象只能自定义行为和形态.不过,要在lua中模拟类也并不困难. lua中,面向对象是用元表这个机制来实现. 首先,一般来说一个表和它的元表是不同的个体(不属于同一个表),在创建新的表时,不会自动创建元表. setmetatable函数:设置元表 setmetatable( 表1 , 表2 )  将表2挂接为表1的元表,并且返回经过挂接后的表1

Lua面向对象设计

面向对象的基础是类,但Lua中没有提供类的概念,所以我们需要利用Lua现有的机制来实现类似于类的有关oop的一整套概念.基本方案是使用table来实现类机制,并且结合使用self参数和冒号操作.我们先来看看self参数和冒号操作符的用法: self参数的使用是很多面向对象语言的要点,大多数OO语言将这种机制隐藏起来,这样程序员不必声明这个参数(虽然仍然可以在方法内使用这个参数).Lua也提供了通过使用冒号操作符来隐藏这个参数的声明(通过冒号来声明函数).先来看下这段代码(这里面还不涉及到类的定义

Lua面向对象编程

Lua中的table就是一种对象,看以下一段简单的代码: 1 local tb1 = {a = 1, b = 2} 2 local tb2 = {a = 1, b = 2} 3 local tb3 = tb1 4 5 if tb1 == tb2 then 6 print("tb1 == tb2") 7 else 8 print("tb1 ~= tb2") 9 end 10 11 tb3.a = 3 12 print(tb1.a) 上述代码会输出tb1 ~= tb2.

Lua 面向对象

面向对象特征 1) 封装:指能够把一个实体的信息.功能.响应都装入一个单独的对象中的特性. 2) 继承:继承的方法允许在不改动原程序的基础上对其进行扩充,这样使得原功能得以保存,而新功能也得以扩展.这有利于减少重复编码,提高软件的开发效率. 3) 多态:同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果.在运行时,可以通过指向基类的指针,来调用实现派生类中的方法. 4)抽象:抽象(Abstraction)是简化复杂的现实问题的途径,它可以为具体问题找到最恰当的类定义,并且可以在最恰当

【quick-cocos2d-x】Lua 面向对象(OOP)编程与元表元方法

版权声明:本文为博主原创文章,转载请注明出处. 面向对象是一种对现实世界理解和抽象的方法,是计算机编程技术发展到一定阶段后的产物. 早期的计算机编程是基于面向过程的方法,通过设计一个算法就可以解决当时的问题.随着计算机技术的不断提高,计算机被用于解决越来越复杂的问题.面向过程式的编程思想很难良好的解决这些复杂的问题,通过面向对象的方法,更利于用人理解的方式对复杂系统进行分析.设计与编程.同时,面向对象能有效提高编程的效率,通过封装技术,消息机制可以像搭积木的一样快速开发出一个全新的系统.  但是

lua面向对象学习随笔 --类与实例

面向对象最基本的就是两点:类,对象. 但是lua是无类型的,要实现面向对象只能模拟实现. 其实他们都是表,多了个__index属性,就模拟出了实现“类和继承”的效果. 面对Lua千万别用c++的类来类比,不然会误入歧途! 它就是一个table而已下面一个典型的定义一个“类”的方式. class={} function class:new(o) local o=o or {} setmetatable(o,self) self.__index=self o:ctor() return o end