学gglua怎么能不会lua的魔法方法?

目录

介绍

0.setmetatable

0.1.__add

0.2.__sub

 0.3.总结

1.常用的元方法

1.1.__index

1.2.__newindex

1.3.__call

1.4.__tostring


介绍

lua的魔法方法是什么呢?这里可以参考py的魔法方法 他实际是为了模拟面向对象编程而出现的概念

魔法方法都是以__两个下划线开头的 这点与py中相同

魔法方法的定义方式与对象类似 而我之前的一篇文章说了 lua的对象就是一个table

但是这里不能直接写在表中 这样lua会认为这是一个普通的方法 而不是魔法方法

魔法方法又叫元方法 lua基础好的朋友就知道了 lua中有一个函数 这个函数的作用是设置元表

而这个方法就是setmetatable这个方法需要两个参数 第一个参数为需要设置的元方法(魔法方法)的对象(表)第二个参数就是包含了元方法(魔法方法)的对象(表)

0.setmetatable

例子

local enumClass = {}

local classFunction = {
    __call = function(self)
        return self
    end
}
setmetatable(enumClass,ClassFunction)

0.1.__add

__add:这个魔法方法用于定义相加操作符(+)的行为。例如,当对两个表进行相加时,Lua 将调用该方法来执行实际的相加操作。

__add(table1, table2):相加操作的参数包括两个表,即被加数和加数。

在lua中 对象是可以被相加(+)的 只是在相加之前 需要手动添加__add元方法 相信写gglua的朋友应该是没有这样写过 但其实是可以的

例如

class={
    value=0
}

metaObjects={
    __add=function(table1,table2)-- table1=被加数 table2=加数
        for i, v in pairs(table2) do
            table1.value=table1.value+v
        end
        return table1.value
    end
}
setmetatable(class,metaObjects)

demoClass={
    value=2,
    age=18
}

print(class+demoClass)-- 20
print(class.value)-- 20

0.2.__sub

__sub:这个魔法方法用于定义相减操作符(-)的行为。类似地,当对两个表进行相减时,Lua 将调用该方法来执行实际的相减操作。

__sub(table1, table2):相减操作的参数包括两个表,即被减数和减数。

例如
 

class={
    value=0
}

metaObjects={
    __add=function(table1,table2)
        for i, v in pairs(table2) do
            table1.value=table1.value+v
        end
        return table1.value
    end,
    __sub=function(table1,table2)
        for i, v in pairs(table2) do
            table1.value=table1.value-v
        end
        return table1.value
    end
}
setmetatable(class,metaObjects)

demoClass={
    value=2,
    age=18
}

print(class-demoClass)-- -20
print(class.value)-- -20

 0.3.总结

这里还有很多类似的元方法 就不一一举例了 大家可以自己手动写一个测试

  1. __mul:这个魔法方法用于定义相乘操作符(*)的行为。当对两个表进行相乘时,Lua 将调用该方法来执行实际的相乘操作。

  2. __div:这个魔法方法用于定义相除操作符(/)的行为。当对两个表进行相除时,Lua 将调用该方法来执行实际的相除操作。

  3. __mod:这个魔法方法用于定义取模操作符(%)的行为。当对两个表进行取模运算时,Lua 将调用该方法来执行实际的取模操作。

  4. __pow:这个魔法方法用于定义乘方操作符(^)的行为。当对两个表进行乘方运算时,Lua 将调用该方法来执行实际的乘方操作。

  5. __unm:这个魔法方法用于定义一元负号操作符(-)的行为。当对一个表应用一元负号时,Lua 将调用该方法来执行实际的负号操作。

  6. __concat:这个魔法方法用于定义字符串连接操作符(..)的行为。当对两个表进行字符串连接时,Lua 将调用该方法来执行实际的连接操作。

  7. __len:这个魔法方法用于定义 # 操作符的行为,它返回表的长度。当对一个表应用 # 操作符时,Lua 将调用该方法来获取表的长度。

  8. __eq:这个魔法方法用于定义相等操作符(==)的行为。当对两个表进行相等比较时,Lua 将调用该方法来判断它们是否相等。

  9. __lt:这个魔法方法用于定义小于操作符(<)的行为。当对两个表进行小于比较时,Lua 将调用该方法来判断它们的大小关系。

  10. __le:这个魔法方法用于定义小于等于操作符(<=)的行为。当对两个表进行小于等于比较时,Lua 将调用该方法来判断它们的大小关系。

  1. __mul(table1, table2):相乘操作的参数包括两个表,即被乘数和乘数。
  2. __div(table1, table2):相除操作的参数包括两个表,即被除数和除数。
  3. __mod(table1, table2):取模操作的参数包括两个表,即被取模数和取模数。
  4. __pow(table1, table2):乘方操作的参数包括两个表,即底数和指数。
  5. __unm(table):一元负号操作的参数为一个表,即被取负数的表。
  6. __concat(table1, table2):字符串连接操作的参数包括两个表,即左字符串和右字符串。
  7. __len(table):返回表的长度,参数为一个表。
  8. __eq(table1, table2):相等比较操作的参数包括两个表,即被比较的两个表。
  9. __lt(table1, table2):小于比较操作的参数包括两个表,即被比较的两个表。
  10. __le(table1, table2):小于等于比较操作的参数包括两个表,即被比较的两个表。

1.常用的元方法

  1. __index:这个魔法方法用于定义对表的索引操作的行为。当你试图访问一个表中不存在的键时,Lua 将调用该方法来返回对应的值。

  2. __newindex:这个魔法方法用于定义对表的新索引操作的行为。当你试图给一个表中不存在的键赋值时,Lua 将调用该方法来执行实际的赋值操作。

  3. __call:这个魔法方法用于定义对表的调用操作的行为。当你像调用函数一样调用一个表时,Lua 将调用该方法来执行实际的调用操作。

  4. __tostring:这个魔法方法用于定义将表转换为字符串的行为。当你尝试将一个表转换为字符串时,Lua 将调用该方法来执行实际的转换操作。

1.1.__index

__index(table, key):对表的索引操作的参数包括一个表和一个键(key),表示要访问的表和索引值。

class={
    value=0
}

metaObjects={
    __index=function(table,key)
        print(key.."被访问")
        table[key]="白"
        return table[key]
    end
}
setmetatable(class,metaObjects)

print(class.value)-- -0
print(class.key)-- key被访问    白

1.2.__newindex

__newindex(table, key, value):对表的新索引操作的参数包括一个表、一个键(key)和一个值(value),表示要赋值的表、索引和值。

这个与__index的区别是newindex是在对不存在的键赋值时才会触发而index是只要访问就会触发

class={
    value=0
}

metaObjects={
    __newindex=function(table,key,value)
        print(key.."被访问 尝试赋值"..value)
        rawset(table,key,value.."白")
    end
}
setmetatable(class,metaObjects)

class.key="作者:"
print(class.value)-- -0
print(class.key)-- 作者:白

需要重点注意 在newindex方法中给表中的字段赋值不能直接 table[key]=value 因为这样当你赋值时table表中还没有key这个字段 所以他还会调用newindex方法 这样就会无线递归 必须使用rawset函数进行赋值

1.3.__call

__call(table, ...):对表的调用操作的参数包括一个表和任意数量的参数,表示要调用的表和传递给表的参数。

这个魔法方法是我个人觉得最好用的(可能是Java写多了) 因为该方法可以实现Java的构造方法 用过的都知道多好用

但是lua实现起来肯定是要复杂一点了 但就算是这样 这也是lua对象的主要实现

但遗憾的是lua想实现每次创建对象都会在栈中开辟内存有点麻烦

直接调用是会调用的同一个内存

class={
    name="",
    age=0,

}

metaObjects={
    __call=function(self,...)
        args={...}
        if #args==2 then
            return self:create(...)
        elseif #args == 0 then
            return self:create2()
        end
    end
}

--- 构造方法
function class:create(name,age)
    self.name=name
    self.age=age
    return self
end

--- 构造方法
function class:create2()
    return self
end

setmetatable(class,metaObjects)

object=class("白",18)-- 创建对象

object2=class()-- 创建对象

print(class.name)-- 白
print(class.age)-- 18

print(object2.name)-- 白
print(object2.age)-- 18

1.4.__tostring

__tostring(table):将表转换为字符串的参数为一个表。

这个在电脑的lua环境 或者手机自己搭的lua环境中比较常用

在gg中用到的不是很多 因为gg默认其实是每个对象(表)都暗含了这个方法

这里注意 不确定是gg每个对象(表)都自动帮我们写了这个方法

因为gg的源码有点史 作者确实每看懂 也有可能是在别的方法实现的 不过都可以理解为gg自动帮我们写了这个魔法方法 作为学习的 其实也不需要深究他是怎么实现的


class={
    name="",
    age=0,
}

metaObjects={
    __call=function(self,...)
        args={...}
        if #args==2 then
            return self:create(...)
        elseif #args == 0 then
            return self:create2()
        end
    end,
    __tostring=function(table)
        local retString=""
        for i, v in pairs(table) do
            retString=retString..i.."="..tostring(v)..","
        end
        return retString
    end
}

function class:create(name,age)
    self.name=name
    self.age=age
    return self
end

function class:create2()
    return self
end

setmetatable(class,metaObjects)

object=class("白",18)

print(class.name)-- 白
print(class.age)-- 18

print(object)-- age=18,create2=function: 00908100,create=function: 0090c7d8,name=白,

  • 27
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值