加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

lua 类, 继承, 面向对象

发布时间:2020-12-14 22:06:47 所属栏目:大数据 来源:网络整理
导读:本文转自:http://www.voidcn.com/article/p-fwzpqsob-xy.html? 感谢作者的分享 1.lua中的类 ? ? lua中其实是没有类的,有的只是表(table),而类之间的继承也就是将父类的表连到了一起,派生类中没有找到的属性和方法就通过元表查找父类 2.lua中类的属性 ? ?

本文转自:http://www.voidcn.com/article/p-fwzpqsob-xy.html? 感谢作者的分享


1.lua中的类

? ? lua中其实是没有类的,有的只是表(table),而类之间的继承也就是将父类的表连到了一起,派生类中没有找到的属性和方法就通过元表查找父类

2.lua中类的属性

? ?classA = {width =10,height=10}

? ?classA={}

? ?classA.width=10

? ?classA.height=10?

? ?两种方法都可以,通过点self.width统一调用

3.类方法

[cpp]? view plain copy
  1. function?Box:collsion()??
  2. ????--?默认第一个参数隐藏传递self,可以通过self.xxx?调用属性和方法??
  3. end??
  4. ??
  5. function?Box.create(self)??
  6. ????--必须手动传递参数self,否则无法用self.xxx调用属性和方法??
  7. end??
函数的声明和调用可以用":"和".",属性调用全部用点"."


4.类与元表的用法

lua查找一个表元素时的规则,其实就是如下3个步骤:

? 4.1.在表中查找,如果找到,返回该元素,找不到则继续

? 4.2.判断该表是否有元表,如果没有元表,返回nil,有元表则继续

? 4.3.判断元表有没有__index方法,如果__index方法为nil,则返回nil;如果__index方法是一个表,则重复1、2、3;如果__index方法是一个函数,则返回该函数的返回值

例如:

copy
    father?=?{??
  1. ????house=1??
  2. }??
  3. son?=?{??
  4. ????car=1??
  5. }??
  6. setmetatable(son,?father)?--把son的metatable设置为father??
  7. print(son.house)??
输出结果是nil,如果代码改为

copy
    father.__index?=?father?--?把father的__index方法指向自己??
  1. son?=?{??
  2. ????car=1??
  3. setmetatable(son,?father)??
  4. print(son.house)??
输出的结果就为1了

这就解释了为什么我们经常在cocos2dx的类中经常见到如下

copy
    local?Box?=?class("Box",?function(filename)??
  1. ????????return?cc.Sprite:create(filename)??
  2. ????end)??
  3. Box.__index?=?Box??
设置Box的元表的__index方法为自己,当派生类"SmallBox"派生自"Box",如果在SmallBox中查找不到的属性和方法,就检索元表,当然不是直接从元表中直接检索,是检索元表下的__index,如果__index为nil,则返回nil,如果__index是一个表,那么就到__index方法所指的表中查找对应的属性和方法

具体可以参考:Lua查找表元素过程(元表、__index方法是如何工作的)

5.Cocos2dx中的类

lua没有面向对象一说,cocos为我们准备了class的lua端函数,我们参考quick的class函数,里面还有对应的例子

copy
    --[[--??
  1. 创建一个类??
  2. ~~~?lua??
  3. --?定义名为?Shape?的基础类??
  4. local?Shape?=?class("Shape")??
  5. ??
  6. --?ctor()?是类的构造函数,在调用?Shape.new()?创建?Shape?对象实例时会自动执行??
  7. function?Shape:ctor(shapeName)??
  8. ????self.shapeName?=?shapeName??
  9. ????printf("Shape:ctor(%s)",?self.shapeName)??
  10. end??
  11. --?为?Shape?定义个名为?draw()?的方法??
  12. function?Shape:draw()??
  13. ????printf("draw?%s",?self.shapeName)??
  14. --??
  15. --?Circle?是?Shape?的继承类??
  16. local?Circle?=?class("Circle",?Shape)??
  17. function?Circle:ctor()??
  18. ????--?如果继承类覆盖了?ctor()?构造函数,那么必须手动调用父类构造函数??
  19. ????--?类名.super?可以访问指定类的父类??
  20. ????Circle.super.ctor(self,?"circle")??
  21. ????self.radius?=?100??
  22. function?Circle:setRadius(radius)??
  23. ????self.radius?=?radius??
  24. --?覆盖父类的同名方法??
  25. function?Circle:draw()??
  26. ????printf("draw?%s,?raidus?=?%0.2f",?self.shapeName,?self.raidus)??
  27. --??
  28. local?Rectangle?=?class("Rectangle",248)"> function?Rectangle:ctor()??
  29. ????Rectangle.super.ctor(self,?"rectangle")??
  30. local?circle?=?Circle.new()?????????????--?输出:?Shape:ctor(circle)??
  31. circle:setRaidus(200)??
  32. circle:draw()???????????????????????????--?输出:?draw?circle,?radius?=?200.00??
  33. local?rectangle?=?Rectangle.new()???????--?输出:?Shape:ctor(rectangle)??
  34. rectangle:draw()????????????????????????--?输出:?draw?rectangle??
  35. ~~~??
  36. ###?高级用法??
  37. class()?除了定义纯?Lua?类之外,还可以从?C++?对象继承类。??
  38. 比如需要创建一个工具栏,并在添加按钮时自动排列已有的按钮,那么我们可以使用如下的代码:??
  39. --?从?cc.Node?对象派生?Toolbar?类,该类具有?cc.Node?的所有属性和行为??
  40. local?Toolbar?=?class("Toolbar",?function()??
  41. ????return?display.newNode()?--?返回一个?cc.Node?对象??
  42. end)??
  43. --?构造函数??
  44. function?Toolbar:ctor()??
  45. ????self.buttons?=?{}?--?用一个?table?来记录所有的按钮??
  46. --?添加一个按钮,并且自动设置按钮位置??
  47. function?Toolbar:addButton(button)??
  48. ????--?将按钮对象加入?table??
  49. ????self.buttons[#self.buttons?+?1]?=?button??
  50. ????--?添加按钮对象到?cc.Node?中,以便显示该按钮??
  51. ????--?因为?Toolbar?是从?cc.Node?继承的,所以可以使用?addChild()?方法??
  52. ????self:addChild(button)??
  53. ????--?按照按钮数量,调整所有按钮的位置??
  54. ????local?x?=?0??
  55. ????for?_,?button?in?ipairs(self.buttons)?do??
  56. ????????button:setPosition(x,?0)??
  57. ????????--?依次排列按钮,每个按钮之间间隔?10?点??
  58. ????????x?=?x?+?button:getContentSize().width?+?10??
  59. ????end??
  60. class()?的这种用法让我们可以在?C++?对象基础上任意扩展行为。??
  61. 既然是继承,自然就可以覆盖?C++?对象的方法:??
  62. function?Toolbar:setPosition(x,?y)??
  63. ????--?由于在?Toolbar?继承类中覆盖了?cc.Node?对象的?setPosition()?方法??
  64. ????--?所以我们要用以下形式才能调用到?cc.Node?原本的?setPosition()?方法??
  65. ????getmetatable(self).setPosition(self,?x,?y)??
  66. ????printf("x?=?%0.2f,?y?=?%0.2f",?y)??
  67. **注意:**?Lua?继承类覆盖的方法并不能从?C++?调用到。也就是说通过?C++?代码调用这个?cc.Node?对象的?setPosition()?方法时,并不会执行我们在?Lua?中定义的?Toolbar:setPosition()?方法。??
  68. @param?string?classname?类名??
  69. @param?[mixed?super]?父类或者创建对象实例的函数??
  70. @return?table??
  71. ]]??
  72. function?class(classname,?super)??
  73. ????local?superType?=?type(super)??
  74. ????local?cls??
  75. if?superType?~=?"function"?and?superType?~=?"table"?then??
  76. ????????superType?=?nil??
  77. ????????super?=?nil??
  78. if?superType?==?"function"?or?(super?and?super.__ctype?==?1)?then??
  79. ????????--?inherited?from?native?C++?Object??
  80. ????????cls?=?{}??
  81. if?superType?==?"table"?then??
  82. ????????????--?copy?fields?from?super??
  83. ????????????for?k,v?in?pairs(super)?do?cls[k]?=?v?end??
  84. ????????????cls.__create?=?super.__create??
  85. ????????????cls.super????=?super??
  86. ????????else??
  87. ????????????cls.__create?=?super??
  88. ????????????cls.ctor?=?function()?end??
  89. ????????end??
  90. ????????cls.__cname?=?classname??
  91. ????????cls.__ctype?=?1??
  92. ????????function?cls.new(...)??
  93. ????????????local?instance?=?cls.__create(...)??
  94. ????????????--?copy?fields?from?class?to?native?object??
  95. do?instance[k]?=?v?end??
  96. ????????????instance.class?=?cls??
  97. ????????????instance:ctor(...)??
  98. ????????????return?instance??
  99. else??
  100. ????????--?inherited?from?Lua?Object??
  101. if?super?then??
  102. ????????????cls?=?{}??
  103. ????????????setmetatable(cls,?{__index?=?super})??
  104. ????????????cls.super?=?super??
  105. ????????????cls?=?{ctor?=?function()?end}??
  106. ????????cls.__ctype?=?2?--?lua??
  107. ????????cls.__index?=?cls??
  108. ????????function?cls.new(...)??
  109. ????????????local?instance?=?setmetatable({},?cls)??
  110. ????????????instance.class?=?cls??
  111. ????????????instance:ctor(...)??
  112. return?instance??
  113. ????????end??
  114. return?cls??
  115. end??

传入是一个父类的话,会调用cls.new函数,然后创建实例,调用ctor构造函数

6. 调用一个实例:

假设派生自一个cocos的类 Sprite

copy
    --?class可以传1、2个参数??
  1. --?@param?类名,内部做记录而已,一般和返回的类名一致即可??
  2. --?@param?如果传参数2?使用当前函数作为构造函数?如果没参数2?默认的构造函数??
  3. local?Box?=?return?cc.Sprite:create(filename)??
  4. ????end)??
  5. --?设置元彪?更改元表默认的元方法??
  6. --?访问table中不存在的字段时,解释器查找__index的元方法,否则返回nil??
  7. --?多用于继承?http://blog.csdn.net/q277055799/article/details/8463883??
  8. Box.__index?=?Box??
  9. Box.isDead?=?false??????--定义属性??
  10. --?构造函数(会自动调用)??
  11. --?外界构造时可以传任意参数XXX. function?Box:ctor(pic_path)??
  12. ????local?function?onNodeEvent(event)??
  13. if?"enter"?==?event?then??
  14. ????????????Box:onEnter(pic_path)??
  15. ????????elseif?"exit"?==?event?then??
  16. ????????????Box:onExit()??
  17. ????end??
  18. ????self:registerScriptHandler(onNodeEvent)??
  19. ????local?function?onUpdate()??
  20. ????self:scheduleUpdateWithPriorityLua(onUpdate,?0)??
  21. function?Box:onEnter(pic_path)??
  22. function?Box:onExit()??
  23. function?Box.create(parent,?position)??
  24. ????local?box?=?Box.New("data/box.png")??
  25. ????parent:addChild(box)??
  26. return?box??
  27. return?Box??

如果是一个table,可以直接使用

copy
    local?Bomb?=?class("Bomb")??


7.我们常见cocos2dx的例子中有大量的extend和tolua.getpeer用法如下:

copy
    local?TimelineTestScene?=?class("TimelineTestScene")??
  1. TimelineTestScene.__index?=?TimelineTestScene??
  2. function?TimelineTestScene.extend(target)??
  3. ????local?t?=?tolua.getpeer(target)??
  4. if?not?t?then??
  5. ????????t?=?{}??
  6. ????????tolua.setpeer(target,?t)??
  7. ????setmetatable(t,?TimelineTestScene)??
  8. return?target??
  9. function?TimelineTestScene.create()??
  10. ????local?scene?=?TimelineTestScene.extend(cc.Scene:create())??
  11. return?scene?????
  12. end??

用的时tolua.getpeer,其实它的功能就相当于调用了class,所以请远离extend吧

copy
    class("TimelineTestScene",?cc.Scene)??
  1. TimelineTestScene.__index?=?TimelineTestScene ?

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读