Lua中面向对象编程

阅读本文需要理解前一篇文章Lua中的元方法

使用特定的对象的弊端

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

在函数中使用全局名称Account很糟糕
首先,这个函数只能针对特定的对象工作
即使针对特定的对象,这个函数也只有在对象保存在特定的全局变量中才能工作。

如果我们改变了对象的名称,whitdraw就不能工作了

a,Account = Account,nil
a.withdraw(100)  --Error

这种行为违反了对象拥有独立生命周期的原则

使用self或this额外的参数

冒号操作符

当通过:调用时,系统会自动传递当前的table给self,例如a.eat(a)相当于a:eat()
传递当前对象给eat方法,这样就提高了table的方法的扩展性了。

-- 本质是使用table进行模拟
​
--定义空表,相当于是一个类
Person = {}
​
---定义局部表引用变量,降低方法引用表字段的耦合性
this =Person
--定义字段
Person.Name="Bob"
Person.Gender = "男"
Person.Age = 18
​
--定义方法
--第一种第一方式(匿名函数)
Person.Speak = function()
    print("人在说话")
end
​
--第二种
function Person.Walking()
    print("人在走路")
end
​
--方法中调用方法
function Person:showInfo()
    print("调用个人信息")
    print("Name:"..this.Name)
    print("Age:"..this.Age)
end
​
--冒号操作符,隐藏了一个self参数
function Person:show()
    print("调用个人信息")
    print("Name:"..self.Name)
    print("Age:"..self.Age)
end
​
--调用
print(Person.Name)
print(Person.Gender)
print(Person.Age)
Person.Speak()
Person.Walking()
​
a = Person
Person = nil
a.showInfo()
​
--相当于a.showInfo(a)
a:showInfo()

New新对象

使用self我们解决了表的方法的通用性问题,但我们想解决创建一个新的Person表对象,又得重写一个表,重新赋值,非常麻烦。所以在Lua中我们先定义好一个原型,通过定义一个new方法,可以很方便的创建一个原型对象(在Lua中还是一个表)。

Player = {
    x = 0, y = 0,
    name = "",
​
    new = function ()
        p = {}
        for k,v in pairs(Player) do
            p[k] = v
        end
        return p
    end,
​
    --错误示范一
    --move = function(x,y)
    --    Player.x = Player.x + x
    --    Player.y = Player.y +y
    --end
​
    --方法一
--[[    move = function(p,x,y)
        p.x = p.x+x
        p.y = p.y +y
    end]]
​
​
}
--方法二 self要配合“:”使用
function Player:move(x,y)
    self.x = self.x +x
    self.y = self.y +y
end
p1 = Player.new()
p1.x = 10;
p1.y = 20;
p1.name = "Bob"
​
p2 = Player.new()
p2.x = 30;
p2.y = 40;
p2.name = "Steve"
​
print(p1.x,p1.y,p1.name)
print(p2.x,p2.y,p2.name)
​
--这里表示了“:”的意思,把本身当做参数传递进去
p1:move(10,10)
p2:move(10,10)
​
print(p1.x,p1.y,p1.name)
print(p2.x,p2.y,p2.name)

方式二:使用到元表
通过__index方法,当表中没有查找到key值时,就会去元表中查找。

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

三、使用到继承

使用new方法创建一个实例对象,然后对这个实例继续调用new方法。然后这个实例就像继承其他方法一样继承了基类的new方法。不过现在执行new方法,它的self参数是自己。

Person = {
    name = 0;
    age = 0;
    New = function(name, age)
        local tab = {}
        setmetatable(tab, Person)
        tab.name = name
        tab.age = age
        return tab
    end;

    ToString = function(self)
        print(self.name, self.age)
    end;

    Work = function(self)
        print(self.name .. "的工作是养老")
    end;
}
---这句话放在外表确保先执行 重建Person
Person.__index = Person;

father= Person.New("yeye", 99)
father:ToString()
father:Work()

print(getmetatable(father).name)

son = father.New("son",18)
son:ToString()
son:Work()

--son son中含有Work方法 就会直接返回
function son:Work()
    print(self.name.."我的工作是开车")
end

son:Work()

print(getmetatable(son).name)

四、多态

Lua天然是多态,一个table没有固定的类型,它的指针指向谁,调用的就是谁的对象。

a= Account:new();
a= spacialAccount:new()


a:display() 调用的是子类的
Account.display(a) 调用的是父类的 以静态的方式调用
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

KindSuper_liu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值