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
  • 相关阅读:
    poj 2728 Desert King
    uva 439 Knight Moves
    hdu 1875 畅通工程再续
    scau实验题 8600 骑士周游问题(有障碍物)
    scau实验题 8596 Longest Ordered Subsequence
    poj 1679 The Unique MST
    uva 527 Oil Deposits
    poj 2533 Longest Ordered Subsequence
    .net 程序员 java 开发入门
    Collation conflict occur at operation on User define funtion & table's column
  • 原文地址:https://www.cnblogs.com/liguangsunls/p/7367470.html
Copyright © 2011-2022 走看看