19 March 2015

定义一个方法,函数闭包实现一个类的概念:

function People(name)
    local self = {}
  --初始化方法,私有的
    local function init()
        self.name = name
    end
   
    self.sayHi = function ()
        print("Hello "..self.name)
    end
 
  --调用初始化
    init()
    return self
end

实例化一个对象:

local p = People("Sure")
p:sayHi()

函数闭包的形式实现类继承:

function Man(name)
    local self = People(name)
     
--  local function init()
--      
--  end
 
    self.sayHello = function ()
        print("Hi "..self.name)
    end
     
    return self
end
 

实例化一个子类对象:

local m = Man("Sure")
--m:sayHello()
m:sayHi()

理解OO的本质

这里可以理解一下OO的本质:

Account = {balance = 0}
function Account.withdraw (v)
   Account.balance = Account.balance - v
end

即等价于:

Account = {
   balance=0,
   withdraw = function (v)
       Account.balance = Account.balance - v
end
} 

这个类中的withdraw是不符合OO的。 因为

a = Account; Account = nil a.withdraw(100.00) – ERROR!

就是说实例名称必须是固定的Account,这是很糟糕的。而要消除这种问题,可以这样:

Account = {
   balance=0,
   withdraw = function (self, v)
       self.balance = self.balance - v
end

} 

也就是在调用的时候把实例名称带进去,也就是:

a1 = Account; Account = nil a1.withdraw(a1, 100.00) – OK

那么这才是OO的,因为这个方法可以用于这个类的每个实例上!

继续来说,这里的self在其他OO语言中是隐藏默认实现的,而lua因为本质上不是OO语言才需要这样写。不过lua提供一种冒号写法来简写:

function Account:withdraw (v)
   self.balance = self.balance - v
end 

同样的,调用也可以用冒号简写: a:withdraw(100.00)

所以说来总结一下: 1. 方法如果写在表内,就不需Class.前缀;如果在表外定义,就需要。 2. 声明时,Class.func(self,v)等价于Class:func(v) 3. 调用时,a.func(a,100)等价于a:func(100) 冒号提供的只是语法层面的便利。

比如这个例子,上面说的三点都涵盖了:

Account = {
   balance=0,
   withdraw = function (self, v)
       self.balance = self.balance - v
end

}

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

Account.deposit(Account, 200.00)
Account:withdraw(100.00)

实例

lua不是OO,new是用表作为metatable,就是说: a = A:new(),就是说用A的格式来创建a,那么在术语上A就可以称为类,a就可以称为实例。

new

quick的function.lua中new的实现,是调用了ctor。从中可以看出,ctor用冒号,调用new时用点号。

function cls.new(...)
            local instance = cls.__create(...)
            -- copy fields from class to native object
            for k,v in pairs(cls) do instance[k] = v end
            instance.class = cls
            instance:ctor(...)
            return instance
end

-EOF-