不止八股---Lua原理笔记(1) 面向对象

本文详细介绍了Lua实现面向对象编程的原理,包括使用`__index`和`self`的概念,以及如何通过封装创建原型对象、实现继承、支持多重继承和管理私有性。通过实例演示展示了这些概念在实际代码中的应用。
摘要由CSDN通过智能技术生成

问题

 简述Lua实现面向对象的原理

思路

语法基础

__index和self

__index:子表找不到某个属性,就会找元表的__index对应的属性

self,类似 this,代表:的调用者,.点号的第一个默认参数

实现思路

一个表就是一个对象

封装: 我们可以认为 定义一个原型对象(类对象),原型对象派生出具体对象。

通过原型对象把self.__index=self,使得具体对象找不到对应方法时候,找元表 __index中的方法(就是原型对象里面找)

另外具体对象通过self来在成员函数中调用自己的成员字段

继承:可以上面同样的手法,从父类的 类对象派生出 子类的 类对象

子类 写的同名函数 ,子类调用的时候,由于自己找的到,所以不会找父类的同名函数

导致子类隐藏父类的同名函数

多重继承:1保存函数传递过来的父类对象,形成一个父类列表

2设置子类的元表的__index 为一个查找函数,这个函数会遍历父类列表 查找有没有对应的 字段

私有性:利用局部变量和闭包,一个表保存保存私有变量,一个表保存public的字段和接口函数

内部public 函数通过闭包 访问私有成员变量,把public 的那个表返回出去

代码

--[[原理
语法基础是 __index和self
__index:子表找不到某个属性,就会找元表的__index对应的属性
self:类似 this,代表:的调用者,.点号的第一个默认参数
local 局部的

封装:怎么共享方法,但是不共享变量,  我们可以认为 定义一个原型对象,具体的对象从原型对象里面出来

继承: 实际上,上方的封装的想法,换个角度就是继承的实现,怎么看,就是把 原型对象和对象
    换成 父类和子类

私有性:利用局部变量,构造表的时候,只返回公开的成员表

怎么区分,本质上都是(表)对象,不过在具体写法规则上可以,类对象,写大写同时可以写方法和默认值
    小写就当他是具体的对象
]]

--###类
-- 所有的对象都是 从原型对象派生出来,共享原型对象的方法
Account={balance=0;}
function Account:new (o)
    o=o or{}
    self.__index=self
    setmetatable(o,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"
    end
    self.balance=self.balance-v
end

--###继承
--[[
    继承: 实际上,上方的封装的想法,换个角度就是继承的实现,怎么看,就是把 原型对象和对象
    换成 父类和子类
]]
--子类
SpecialAccount=Account:new()
--具体对象   
s=SpecialAccount:new{limit=1000.00}
--子类盖住父类方法(注意不是重写)
function SpecialAccount:withdraw(v)
    if v-self.balance>=self:getLimit() then
        error"insufficient funds"
    end
    self.balance=self.balance-v
end

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

--###多重继承
--创建子类的时候,设置元表index 为查询父类 函数的函数
--在表 plist 列表查找‘k'
local function search(k,plist)
 for i=1,#plist do
    local v=plist[i][k] --尝试第i个超类
    if v then return v end
 end
end

function  createClass(...)
    local c={}--新类
    local parents={...}--父类列表

    --父类列表中查找缺少的办法,  --t是调用者,这里顶替第一个默认参数(调用者) 
    --下面的例子,account 为t, getName为k
    setmetatable(c,{__index =function (t,k)
        return search(k,parents)
    end})

    -- 将c作为其实例的元表
    c.__index=c;

    --为新类定义一个新的构造函数
    function  c:new(o)
        o=o or {}
        setmetatable(o,c)
        return o
    end

    return c --返回新类
end

Named={}

function  Named:getName()
    return self.name
end

function  Named:setName(n)
    self.name=n
end

NamedAccount =createClass(Account,Named)

account= NamedAccount:new{name="Paul"}
print(account:getName())

-- account:getName()== account.getName(account)==account["getName"](account)
--account 找原型 NamedAccount  然后找 元表index 调用方法
--找父类列表的方法

--####私有性
function  newAccount(initalBalance)
    --私有变量
    local self={balance =initalBalance,
LIM=1000.00}
    local withdraw=function (v)
        self.balance=self.balance-v        
    end
    local deposit=function (v)
        self.balance=self.balance+v    
        
    end
    local getBalance=function ()return self.balance end

    --私有方法
    local extra=function ()
        if self.balance>self.LIM then
            return self.balance*0.10
        else
            return 0;
        end
    end

    local getBalanceExtra=function ()return self.balance +extra() end
    
    return {
        withdraw=withdraw,
        deposit=deposit,
        getBalance=getBalance,
        getBalanceExtra=getBalanceExtra
    }
    
end
acc1=newAccount(100.00)
acc1.withdraw(40.00)
print(acc1.getBalanceExtra())

acc2=newAccount(10000)
print(acc2.getBalanceExtra())

另外还有我经常用的唐老师的写法


Object={}

function Object:new()
    local obj={}
    --把自己设置为index,利用index特性:
    --先找自己表有没有这个属性,没有找index(这里直接就是index),然后再没有找元表,元表的index,再找元表的元表,如果没有元表和这个属性返回nil
    --self.__inde =self是使得自身表拥有Index特性
    self.__index=self;
    -- 调用者作为元表
    setmetatable(obj,self);
    --返回调用者的子表
    return obj;
end

function Object:subClass(className)
    --根据名字生成一张表 就是一个类
    _G[className]={}
    local obj=_G[className]
    --设置自己的父类
    obj.base=self
    --子类设置元表
    self.__index=self;
    setmetatable(obj,self)
end




引用

小y老师的八股

【Unity面试篇】Unity 面试题总结甄选 |热更新与Lua语言 | ❤️持续更新❤️-腾讯云开发者社区-腾讯云 (tencent.com)

是函数覆盖还是函数隐藏,上面我比较严谨的考究了下

C++中函数重载、隐藏、覆盖和重写的区别-腾讯云开发者社区-腾讯云 (tencent.com)

上面的主要内容 来自

Lua程序设计(第4版) (豆瓣) (douban.com)

唐老师的Lua面向对象代码

Lua面向对象之封装【重点】_哔哩哔哩_bilibili

后记

是什么促使我去发csdn了

1.某笔记软件好像限制文档数,感觉笔记要写好多,不够用了

2.前几天我看到q群里面大佬都在写博客,所以想尝试下

3.感觉以前写了好多重复的笔记,而且内容质量非常的低下,导致我复习的时候看自己的笔记都绷不住了,想通过csdn约束自己的笔记质量

4.以前有位前辈和我们说,要懂得量化自己的成果,我之前写了好多笔记,看了好的杂七杂八的,但最终好像没什么成果,还是希望通过这个记录自己的学习成果,避免重复写笔记,也告诉未来的自己,这段时间到底学了啥,干啥成果,不会后悔说,啊我怎么怎么懒,我有好好努力的(

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值