Lua 面向对象

面向对象特征

  • 封装:指能够把一个实体的信息、功能、响应都装入一个单独的对象中的特性。
  • 继承:继承的方法允许在不改动原程序的基础上对其进行扩充,这样使得原功能得以保存,而新功能也得以扩展。这有利于减少重复编码,提高软件的开发效率。
  • 多态:同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。在运行时,可以通过指向基类的指针,来调用实现派生类中的方法。
  • 抽象:抽象(Abstraction)是简化复杂的现实问题的途径,它可以为具体问题找到最恰当的类定义,并且可以在最恰当的继承级别解释问题。

Lua中的面向对象

在lua中,可以使用table + function来模拟类。

以下简单的类包含了三个属性: area, length 和 breadth,printArea方法用于打印计算结果:

-- Meta class
-- 定义方法new,printArea
-- self是lua的关键字,类似于this,指调用者本身,如Shape:new,self指Shape。
-- Shape:new 另一种写法是Shape.new,调用时也要改成.的形式。

Shape = {area = 0}

-- 基础类方法 new
function Shape:new (o,side)
  o = o or {}
  setmetatable(o, self)     -- 设置o的元表为self,当调用Shape中的方法时,self等价于Shape。
  self.__index = self       -- 当在o中找不到key时,lua会找元表中__index对应的函数或者table。
  side = side or 0
  self.area = side*side;
  return o
end

-- 基础类方法 printArea
function Shape:printArea ()
  print("面积为 ",self.area)
end

-- 创建对象
myshape = Shape:new(nil,10)

myshape:printArea()           --> 面积为100

Lua中的继承

-- Meta class
Shape = {area = 0}
-- 基础类方法 new
function Shape:new (o,side)
  o = o or {}
  setmetatable(o, self)
  self.__index = self
  side = side or 0
  self.area = side*side;
  return o
end
-- 基础类方法 printArea
function Shape:printArea ()
  print("面积为 ",self.area)
end

-- 创建对象
myshape = Shape:new(nil,10)
myshape:printArea()           -->面积为    100

Square = Shape:new()               -- Square继承Shape类。
-- 派生类方法 new
function Square:new (o,side)       -- 函数的重写。
  o = o or Shape:new(o,side)
  setmetatable(o, self)
  self.__index = self
  return o
end

-- 派生类方法 printArea
function Square:printArea ()       -- 函数的重写。
  print("正方形面积为 ",self.area)
end

-- 创建对象
mysquare = Square:new(nil,10)
mysquare:printArea()          -->正方形面积为     100

Rectangle = Shape:new()          -- Rectangle继承Shape类。
-- 派生类方法 new
function Rectangle:new (o,length,breadth)  -- 函数的重写。
  o = o or Shape:new(o)
  setmetatable(o, self)
  self.__index = self
  self.area = length * breadth
  return o
end

-- 派生类方法 printArea
function Rectangle:printArea ()   --函数的重写
  print("矩形面积为 ",self.area)
end

-- 创建对象
myrectangle = Rectangle:new(nil,10,20)
myrectangle:printArea()       -->矩形面积为  200

另一个实例

Account = {balance = 0}    

function Account:new(o)   
    o = o or {}           
    setmetatable(o,self)      
    self.__index = self              
    return o  
end  

function Account:deposit(v)  
    self.balance = self.balance + v  
end  

function Account:withdraw(v)  
    if v > self.balance then  
        error "insufficient funds"  
    else  
        self.balance = self.balance - v  
    end  
end  

----------------------------------------------------------------  

a = Account:new({balance = 200})  
a:deposit(100)                     --a没有deposit字段,所以会使用Account的deposit方法  
print(a.balance)                   --300  

b = Account:new()  
print(b.balance)                   --0  

c = b:new({limit = 1000})          --b从Account中继承了new,而b中的new方法,self代表的是b  
--因此,c的元表为b,b中的__index字段为b,c继承b,b继承Acount  
c:deposit(500)  
print(c.balance)                   --500  

----------------------------------------------------------------  

--[[  
b可以重写从Acount中继承的方法  
]]  

function b:getLimit()  
    return self.limit or 0  
end  

function b:withdraw(v)  
    if v - self.balance >= self:getLimit() then  
        error "insufficient funds"  
    else  
        self.balance = self.balance - v  
    end  
end  

c:withdraw(700)                     --c会先从b中找withdraw  
print(c.balance)                    -- -200  
print(c:getLimit())                 --1000  

----------------------------------------------------------------  

function c:getLimit()  
    return self.balance * 0.1  
end  

print(c:getLimit())                 -- -20 

你可能感兴趣的:(Lua)