2.12 Lua中的面向对象

面向对象是一种新兴的程序设计方法,是一种新的程序设计规范,其基本思想是使用对象、类、继承、封装、消息等基本概念来进行程序设计。从现实世界中客观存在的事物(即对象)出发来构造软件系统,并且在系统构造中尽可能运用人类的自然思维方式。

面向对象最重要的两个概念就是:对象和类。

对象是系统中用来描述客观事物的一个实体,它是构成系统的一个基本单位。一个对象由一组属性和对这组属性进行操作的一组函数组成。

类是具有相同属性和函数的一组对象的集合,它为属于该类的所有对象提供了统一的抽象描述,其内部包括属性和函数两个主要部分。但是需要注意的是,Lua语言中并没有提供类的定义能力,但可以把table类型变量当成对象使用。

2.12.1 Lua中的对象

在Lua语言中虽然不能定义类,但可以将table类型变量当成对象,对象具有数据和操作。我们使用table类型描述学生对象如下:

      Student = {id = 100, name ="Tony"}                                               ①

      function Student.toString()                                                     ②
        local s ="Name:"..Student.name .."id:"..Student.id
        return s
      end

第①行代码定义Student对象,其中的id和name是两个数据成员,第②行代码的Student.toString()函数是对象的操作,toString()函数只能属于Student对象,这种属于特定对象的函数被称为“方法”,出于习惯我们在本书中仍然将这些方法称为函数。

在面向对象的语言中一般都有代替本身对象代词,Java和C++用的是this, Objective-C中是self,而Lua可以使用self表示自身对象。

      Student = {id = 100, name ="Tony"}

      function Student:toString()                                                     ①
        local s ="Name:"..self.name .."id:"..self.id                                 ②
        return s
      end

      print(Student:toString())                                                      ③

上述代码第①行是定义Student:toString()函数,其中Student与toString()之间是用冒号“:”,而不是点“.”,冒号表示的函数参数中省略了self,第①行的函数也可以写成function Student.toString(self)。

第②行代码中使用了self代替了Student对象。

第③行代码是访问Student对象的toString()函数,也是用冒号“:”访问toString()函数的。

2.12.2 类的实现

Lua中并没有类的定义,但是我们可以自己实现类,类是对象的模板,一个类能够创建出多个对象。实现类的思路是把Student作为原型对象,原型就是一个模板,通过Student原型来创建其他的对象,那么我们就可以将Student原型对象称为“类”了。创建的对象遇到一个未知操作时,会到Student原型中去查找,这也符合类的继承原则。

Student类的示例代码如下:

      Student = {id = 100, name ="Tony"}

      function Student:toString()
        local s ="Name:"..self.name .."id:"..self.id
        return s
      end

      function Student:create(o)                                                       ①
        o = o or{}                                                                     ②
        setmetatable(o, self)                                                         ③
        self.__index= self                                                            ④
        return o
      end

      student1 = Student:create({id = 200, name ="Tom"})                               ⑤
      print(student1:toString())

      student2 = Student:create({id = 300, name ="Ben"})                               ⑥
      print(student2:toString())

上述代码第①行是定义Student:create(o)函数,其中o是table类型的参数。第②行代码o = o or{}是当参数o没有创建时候,重新创建一个空的table。

第③行代码setmetatable(o, self)是把self当作元表(Metatable)设置给o对象,元表是Lua中的重要概念,每一个table都可以加上元表,元表可以改变相应的table的行为。

代码第④行self.__index = self表示,首先在当前对象中查找操作,如果当前对象中没有,就会到原型Student中查找操作。

第⑤行代码是通过Student原型(类)创建student1对象,第⑥行代码是通过Student原型(类)创建student2对象。