zoukankan      html  css  js  c++  java
  • cocos2d-Lua02Lua面向对象

    1 Lua中的面向对象

    1.1 问题

    lua不是一个面向对象的语言。可是他又有面向对象的思想。

    lua中的面向对象是伪面向对象。伪面向对象就要用到table实现。

    由table模拟了一个面向对象的编程, table事实上也能够看做是一个对象。和其它语言对象一样有个自身的标示(self),具有自己的生命周期。本案例演示lua中的面向对象。

    1.2 方案

    首先用table实现面向对象。

    然后通过self得到当前lable对象。

    接下来通过 : 符号实现声明函数时的隐试參数self。

    最后通过require返回对象,调用该对象方法。

    1.3 步骤

    实现此案例须要依照例如以下步骤进行。

    步骤一:用table实现面向对象

    首先定义一个table类型的数据Account。然后声明label对象。通过对象调用方法,代码例如以下所看到的:

    1. Accout = {balance = 0}
    2. functionAccout.count( v )
    3.     print ("value is "..v)
    4. end
    5. --声明label对象(变量)accout
    6. accout = Accout
    7. --通过对象调用方法
    8. accout.count(1000)

    编辑器中的效果如图-13所看到的:

    图-13

    步骤二:通过self得到当前lable对象

    通过对象调用方法。显示的把accout这个table 这个对象传入到函数 (显示的传入 self),还可通过冒号调用的方式隐试的传入self对象代码例如以下所看到的:

    1. Accout = {balance = 10}
    2. --显示传入self
    3. functionAccout.count( self, v )
    4.     self.balance = self.balance + v;
    5.     print ("value is "..self.balance)
    6. end
    7. --声明label对象(变量)accout
    8. accout = Accout
    9. --通过对象调用方法, 显示的把accout这个 table 这个对象传入到函数 (显示的传入 self)
    10. accout.count(accout, 1000)
    11. --还可通过 : 调用的方式隐试的传入 self 对象
    12. accout:count(2000)

    编辑器中的效果如图-14所看到的:

    图14

    步骤三:通过冒号实现声明函数的隐式參数

    通过冒号符号隐式传入self。还可通过冒号调用的方式隐式的传入self对象,代码例如以下所看到的:

    1. Accout = { balance = 10}
    2. --通过 : 符号, 隐试传入 self
    3. functionAccout:count( v )
    4.     self.balance = self.balance + v;
    5.     print ("value is "..self.balance)
    6. end
    7. --声明label对象(变量)accout
    8. accout = Accout
    9. --还可通过 : 调用的方式隐试的传入 self 对象
    10. accout:count(2000)

    编辑器中的效果如图-15所看到的:

    图-15

    步骤四:通过require 返回对象

    通过require 返回对象,调用该对象方法,代码例如以下所看到的:

    1. class = require("myClass")
    2. --函数写在 table的括号外
    3. class:showName()
    4. --函数写在 table的括号内
    5. class.show(class)

    编辑器中的效果如图-16所看到的:

    图-16


    -------------》require(“XXX”)  --  仅仅运行一次,避免了反复运行


    1.4 完整代码

    本案例中。完整代码例如以下所看到的:

    1. --[[lua不是一个面向对象的语言。可是他又有面向对象的思想
    2. lua中的面向对象是伪面向对象,伪面向对象就要用到table实现。
    3. 是table模拟了一个面向对象的编程。 table事实上也能够看做是一个对象,
    4. 和其它语言对象一样有个自身的标示(self)。具有自己的生命周期。]]
    5. --1.用table实现面向对象
    6. Accout = {balance = 0}
    7. functionAccout.count( v )
    8.     print ("value is "..v)
    9. end
    10. --声明label对象(变量) accout
    11. accout = Accout
    12. --通过对象调用方法
    13. accout.count(1000)
    14. --2.通过 self 得到当前 lable 对象
    15. Accout = {balance = 10}
    16. --显示 传入 self
    17. functionAccout.count( self, v )
    18.     self.balance = self.balance + v;
    19.     print ("value is "..self.balance)
    20. end
    21. --声明label对象(变量) accout
    22. accout = Accout
    23. --通过对象调用方法, 显示的把 accout 这个 table 这个对象传入到函数 (显示的传入 self)
    24. accout.count(accout, 1000)
    25. --还可通过 : 调用的方式 隐试的传入 self 对象
    26. accout:count(2000)
    27. --3.通过 : 符号,实现声明函数时的 隐试參数 self
    28. Accout = { balance = 10}
    29. --通过 : 符号, 隐试 传入 self
    30. functionAccout:count( v )
    31.     self.balance = self.balance + v;
    32.     print ("value is "..self.balance)
    33. end
    34. --声明label对象(变量) accout
    35. accout = Accout
    36. --还可通过 : 调用的方式 隐试的传入 self 对象
    37. accout:count(2000)
    38. --4.通过require 返回对象, 调用该对象方法
    39. class = require("myClass")
    40. --函数写在 table的括号 外
    41. class:showName()
    42. --函数写在 table的括号 内
    43. class.show(class)
    2、元方法与元表
    元方法:就是两个 类型 变量之间进行操作的 函数
    比如,1.数字的相加。它可能不过一个函数:1 + 1--->add(1,1)--->add函数就是用来计算两个数字间相加的结果de
    2.table类型相加?--->Lua中不存在两个{} + {}的元方法。
    元表(metatable):就是用来存放 元方法 的 table,是table提前定义的一系列操作。把两个table相加,那么Lua就会先去检查两个table是否有metatable,然后再检 查metatable中是否有__add方法。

    假设有依照__add方法中的操作来运行,否则,报错。

    比如,假设非要将两个table类型相加的话,直接执行必报错。

    但Lua同意改动元表,例如以下所看到的:

    一个元表,事实上就是一个table值,所以,我们仅仅须要新建一个table,加入元方法就可以。

    比方加法运算的元方法就是:__add,这是Lua规定的。

    仅仅要某个值的元表里含有__add这个元方法。那就能够使用+号进行运算。

     

    例如以下代码:

    1.     -- 创建一个元表
    2.     local mt = {};
    3.     mt.__add = function(t1, t2)
    4.         print("两个table相加的结果就是...Good Good Study,Day Day Up!");
    5.     end
    6.     local t1 = {};
    7.     local t2 = {};
    8.    
    9.     -- 给两个table设置新的元表
    10.     setmetatable(t1, mt);
    11.     setmetatable(t2, mt);
    12.    
    13.     -- 进行加法操作
    14.     local result = t1 + t2;

    首先创建了一个table变量mt,给这个table新增一个元素__add。这个table就拥有了作为元表的资格了。

    然后创建两个新的table变量。使用setmetatable函数给table设置新的元表。此时,两个table变量就以mt作为元表了。

    最后,对t1和t2进行加法操作。这时就会从元表中查找__add元方法。假设找到的话,就调用这个元方法对两个变量进行加法操作。


    Lua中的每个值都有或者能够有一个元表,但table和userdata能够拥有独立的元表,其它类型的值就仅仅能共享其类型所属的元素。比方字符串使用的是
    string的元表。注意:Lua在新建table时,不会创建metatable,须要使用setmetatable来设置元表。setmetatable的參数能够使随意table,包含要赋值的table本身。


    ------》查看一个变量是否有元表:
    print(getmetatable(a)) -- nil 表示没有元表


    Lua中的重要的元方法:__eq等于、__lt小于、__le小于等于、__add:加法、__sub:减法、__mul:乘法、__div:除法、__unm:相反数、__mod:取模、__pow:乘幂、__index function(table,key)、__newindex function(table,key,value)、__tostring 被print()调用、__metatable设置后可隐藏mt

    仅仅要在自己定义元表的时候,给这些元方法名赋予新的函数就能够实现自己定义操作了。

    Lua訪问table元素 首先。通过__index元方法来查找是否有这个函数(假设没有。返回nil);__index的值能够直接是一个table。也能够是函数(若是table,则以该table作为索引进行查询。若是函数。则将table和缺少的域作为參数,调用这个函数)


     样例1、

    我们新建一个自己定义的元表(也就是一个table变量)。用来定义一些操作:

    1.     -- 创建一个元表
    2.     local mt = {};
    3.     mt.__add = function(s1, s2)
    4.         local result = "";
    5.         if s1.sex == "boy" and s2.sex == "girl" then
    6.             result = "青梅竹马";
    7.         elseif s1.sex == "girl" and s2.sex == "girl" then
    8.             result = "空对空";
    9.         else
    10.             result = "硬碰硬"
    11.         end
    12.        
    13.         return result;
    14.     end

     

    事实上这和上一节的样例基本一样。仅仅是多说一次而已,使用方式例如以下:

    1.     -- 创建两个table,能够想象成是两个类的对象
    2.     local s1 = {
    3.         name = "Hello",
    4.         sex = "boy",
    5.     };  
    6.     local s2 = {
    7.         name = "Good",
    8.         sex = "girl",
    9.     };
    10.    
    11.     -- 给两个table设置新的元表
    12.     setmetatable(s1, mt);
    13.     setmetatable(s2, mt);
    14.    
    15.     -- 进行加法操作
    16.     local result = s1 + s2;
    17.    
    18.     print(result);
    样例2、
    Window = {}
    Window.mt = {}
    Window.prototype = {x = 0,y = 0,width = 100,height = 100}
    Window.mt.__index = function(table,key)
    return Window.prototype[key]
    end
    function Window.new(t)
    setmetatable(t,Window.mt)
    return t
    end
    --測试
    w = Window.new{x = 10,y = 20}
    print(w.heigth)
    __newindex的使用方法基本与样例2一致。差别在于__newindex的作用是用于table的更新,__index用于table的查询操作。

    当对table中不存在的索引赋值时,就会调用__newindex元方法。组合使用__index和__newindex能够实现非常多功能
    封装:
    有了元表(metatable)之后。Lua类的封装就会变得非常easy。仅仅要为table加入metatable,并设置__index方法。
    比如:
    People = {age = 18}
    function People:new()
    local p = {}
    setmetatable(p,self)
    self.__index = self
    return p
    end
    function People:groupUp()
    self.age = self.age + 1
    print(self.age)
    end
    --測试
    p1 = People:new()
    p1:growUp() --19
    p2 = People:new()
    p2:growUp() --19
    --[[执行结果能够看出:两个对象拥有的age成员是全然独立的。并且全部的有关People的方法都能够对外不可见,这样全然实现了面向对象中的类的封装--]]
    继承:
    继承是面向对象中不可缺少的一部分。依旧使用上例中的People,展示Lua中实现继承的方法。

    创建一个People实例Man,再在Man上重写People的同名方法:

    Man = People:new()
    function Man:growUp()
    self.age = self.age + 1
    print("man's growUp:"..self.age)
    end
    --測试
    man1 = Man:new()
    man1.growUp() --man's growUp:19
    多态:
    Lua不支持函数多态,而支持指针的多态,因为Lua动态类型的特性,本身就能支持。

    person = People:new()
    person:growUp() --People's growUp:19
    person = Man:new()
    person:growUp() --Man's growUp:19
  • 相关阅读:
    Tomcat
    二叉树
    CDOJ 1962 天才钱vs学霸周2【最大流】
    次小生成树(POJ1679/CDOJ1959)
    CDOJ1927 爱吃瓜的伊卡洛斯(2) 【并查集】启发式合并+set
    HDU 1074 Doing Homework(DP状态压缩)
    uva 11367 (Dijkstra+DP)
    线段树模板
    openpose pytorch代码分析
    opencv图片坐标和数组下标
  • 原文地址:https://www.cnblogs.com/liguangsunls/p/7367470.html
Copyright © 2011-2022 走看看