Lua面向对象编程的基本原理示例,你明白几分?

网站建设4年前发布
24 0 0

Lua语言是一个小而美的语言,使用者不多。,估计阅读这篇文章的人也不会多,姑且当做一篇笔记吧。,这篇文章主要描述:在Lua语言中,如何通过table结构来实现面向对象编程。,主要是看到某鸟教程上错误百出,估计示例代码自己都没有测试过;,关于Lua语言中的table以及metatable的基本知识,这里就不赘述了,官方手册中描述的很清楚。,执行结果如下:,基类(父类) A,首先来分析下4-25行的代码。,4-9行:定义父类A的成员变量和函数(按照C++中的习惯,可以叫做方法),可以看出Lua语言中的函数是“一等公民”,是可以赋值给一个变量的。,11-16行:相当于是构造函数,用来创建一个父类A的对象。,18-20行:给父类A增加一个函数,待会在分析子类B的时候再说。,22行:调用A:new()函数,创建一个类A的对象,赋值给变量objA。,在A:new()函数中,关键是第13行代码:此时self等于A,就相当于是A.__index = A,这是合法的。,因为函数的调用方式是A:new(),Lua的语法糖会把A作为第一个参数传递给new()函数的第一个隐藏参数self。,然后执行14行的setmetatable(t, self),相当于把表t的元表设置为A。,以上两行搞明白之后,23-24行的打印语句就简单了:,23行:因为表objA中没有成员a,但是objA被设置了元表A,而且该元表A带有__index属性,该属性的值是表A自己,于是就到A中查找是否有成员a,于是就打印出:,__index 属性的值,可以是一个表,可以是一个函数;,只不过这里特殊一点:__index 设置为 A 自己;,24行:查找函数的过程是一样的,找到元表A的__index属性的值,也就是表A自己中的funcA函数,然后调用,打印出:,派生类(子类) B,28-33行:定义了子类B,其实它也是一个对象。,在创建函数A:new(t)中,参数t的值是:,此时,self仍然是父类A,B的创建过程与objA的创建过程是一样的,只不过给参数t设置了子类B自己的成员变量和函数。,所以,B的元表被设置为A(14行代码的功劳),当然了A的__index仍然被设置为A自己。,关键是35行:objB = B:new(),得仔细唠唠。,子类B并没有自己的new函数,但是类B(也是一个 table) 的元表被设置为A,并且A.__index = A,所以最终就找到了A中的new函数,也就是11-16行代码。,进入这个函数中时,第一个隐藏参数self被设置为 B 了,因为函数调用形式是:B:new()。,所以:,new()函数返回之后,就把t赋值给objB。,下面再看一下36-39行的打印语句:,36行:objB中并没有成员a,但是objB的元表是B,而且B.__index = B,所以就到B中去查找a。,虽然B中也没有a,但是B的元表是A,而且A.__index = A,所以就在A中找到了成员a,打印出:,37行:objB中并没有成员b,但是objB的元表是B,而且B.__index = B,所以在B中找到了成员b,因此打印出:,37和38行的查找过程是类似的,只不过换成了函数而已。,子类对象操作自己的变量,41行:objB:myadd(10)。,查找myadd函数的过程与查找obj.a的过程是一样的,这里再唠叨一遍:,于是就调用了函数:,而且self等于objB,因此函数体中就等于是:,加法表达式中的objB.a的读取过程,上面已经描述过了,最终定位到的是父类A中的a,即:1。,1 + 10 = 11,然后把11赋值给objB.a。,在赋值操作中,被赋值的objB.a就不再是父类A中的那个a了!,因为objB本质是一个table,给objB设置键值对的时候:,根据上面这个规则,就会设置objB.a = 11。,明白以上这些之后,42和43行的打印语句就不复杂了。,42行:objA最终找到的a是父类A中的成员a,打印出:objA.a = 1。,43行:objB中自己已经有了成员a,所以打印出:objB.a = 11。,有了上面的基础,再从子类B中派生出类C,C派生出类D... 都不是什么问题了,如下所示:,感兴趣的读者可以自己测试一下。

© 版权声明

相关文章