zoukankan      html  css  js  c++  java
  • lua学习笔记(十一)

     
    面向对象编程
       对象的实现
        在lua中table就是一种对象
            1.有自己的状态
            2.有自己的唯一标识self
            3.有自己的生命周期
        使用table可以自己实现面向对象的几乎所有特性
        把函数定义在table中,并使用t.func的形式访问,如同方法调用
        Account = {balance=0}
        function Account.withdraw(v)
            Account.balance = Account.ballance - v
        end
        但在函数中使用全局的Account是一个不好的习惯
        在lua中使用面向对象方式编程时尽量使用self和t:func的形式    
        带有标识自身对象的方法定义:
        function Account.withdraw(self, v)
        同上的语法糖定义:
        function Account:withdraw(v)
        带有标识自身对象的方法调用:
        a1.withdraw(a1, v)
        同上的语法糖定义:
        a1:withdraw(v)
        使用":"会把自身当做每一个参数隐式的传入
        使用self是面向对象编程的一大核心,很多语言为程序员隐藏了这个参数
        self在C++中就相当于this指针
       类的实现    
        在lua中没有类的概念,但可以自己来实现
        function Account:new(o)
            o = o or {} --如果用户没有提供table,则创建一个
            setmetatable(o, self)
            self.__index = self
            return o
        end
        当使用new函数来创建对象后(其实就是创建一个新的table),所有的访问都会从Account这个table里找
        这种情况就相当于Account是一个类,也可以说是一个原型模具,所有新创建的table都拥有他的属性和方法
        a = Account:new{balance=0}
        a:deposit(100.00)
        由于deposit在新创建的table a里没有定义
        因此通过它的元表__index来查找,a的元表是Account,
        因此会调用Account的deposit方法,但self传入的是a
        这就实现了a继承了Account的方法deposit
        在这里也看到了使用self来标识调用对象的好处
       继承和派生
        sa = Account:new()
        s = sa:new{limit=1000.00}
        第一行sa继承了Account,sa的元表是Account,找不到的方法就去Account里去找
        第二行s继承了sa,这里的new是Account的方法但传入的self是sa,
        致使s的元表是sa而sa的元表又是Account
        所以一层一层的继承了下去,并且在每一层的派生table里都可以定义重载方法和新的方法
        在lua里的可以实现多重继承,就是使元表的__index指向一个函数,然后自行判断并处理
       私密性
        使用table来实现面向对象的编程方式,几乎可以实现所有面向对象的编程特性
        但它没有也不想去实现的就是对象的私密性,也就是c++里的private、public、protected
        这与lua设计的初衷有关,lua定位于小型的程序开发,参与一个工程的人不会很多,自行约束
        非要实现私密性的话lua也不是不能,只是不能再使用table和元表的方式了
        可以使用函数闭包来实现私密性:
        function newAccount(init)
             local self = {blance=init}
             local withdraw = function(v)
                 self.balance = self.balance - v
             end
             local deposit = function(v)
                 self.balance = self.balance + v
             end
             return{withdraw = withdraw, deposit = deposit}
        end
        在闭包里定义一个table的upvalue,然后把所有闭包函数都定义在这里table里,
        然后返回这个table,用key访问内部方法
        使用闭包实现对象的方式比用table效率高并实现了绝对的私密性,但无法实现继承,相当于简单的小对象
        甚至可以在闭包里仅定义一个方法,然后通过key来判断调用是什么方法
        Tcl/Tk对它的窗口部件就使用这种方法
     
  • 相关阅读:
    BZOJ3435: [Wc2014]紫荆花之恋(替罪羊树,Treap)
    BZOJ2668: [cqoi2012]交换棋子(费用流)
    codeforces111D. Petya and Coloring(组合数学,计数问题)
    codeforces1114D. Flood Fill(区间Dp)
    BZOJ2137: submultiple(生成函数,二项式定理)
    BZOJ3645: Maze(FFT多项式快速幂)
    codeforces 140E.New Year Garland
    BZOJ1194: [HNOI2006]潘多拉的盒子(tarjan)
    BZOJ2337: [HNOI2011]XOR和路径(高斯消元,期望)
    BZOJ3569: DZY Loves Chinese II(线性基构造)
  • 原文地址:https://www.cnblogs.com/lifesteven/p/4169410.html
Copyright © 2011-2022 走看看