lua __index __newindex upvalue 示例

项目中有个公会对象,数据大部分存在data中,之前都是 u.data.point这样访问,太麻烦了。

于是通过设置__index 使之可以直接访问属性,u.point。

但是还是不能直接改属性,u.point = 4,所以再设置了__newindex。

 

在设置了setmetatable之后,不能直接给u添加新属性,因为设置了__newindex,新的属性将直接加到u.data中的。

 

[c-sharp] view plaincopyprint?
  1. Union = {  
  2.     data = nil,  
  3.     dirty = nil,  
  4. }  
  5. --- 生成新的对象  
  6. function Union:new(o)  
  7.     o = o or {}  
  8.     setmetatable(o,self)  
  9.     self.__index = self  
  10.     return o  
  11. end  
  12. --- 初始化Union数据  
  13. function Union:init(data)  
  14.     self:initTable()  
  15.     self.data = data  
  16.     local meta = {}  
  17.     meta.__index = function (table, key)  
  18.         if Union[key] ~= nil then  
  19.             return Union[key]  
  20.         else  
  21.             return self.data[key]  
  22.         end  
  23.     end  
  24.     meta.__newindex = function(table,key, value)  
  25.         self.data[key] = value  
  26.     end  
  27.     setmetatable(self, meta)  
  28. end  
  29. function Union:initTable()  
  30.     if self.data == nil then  
  31.         self.data = {}  
  32.     end  
  33.     if self.dirty == nil then  
  34.         self.dirty = {}  
  35.     end  
  36. end  
  37. function Union:print()  
  38.     print(self.point, self.data.point)  
  39. end  
  40. function pt()  
  41.     print(data1.point, data2.point, u.point, u.data.point)  
  42. end  
  43. u = Union:new()  
  44. data1 = {point = 3}  
  45. data2 = {point = 103}  
  46. u:init(data1)  
  47. pt()  
  48. u.point = 4  
  49. pt()  
  50. u.data = data2  
  51. pt()  
  52. u.point = 104  
  53. pt()  

 

 

 

通过修改__index和__newindex会获得不同的结果。

 

1.正确结果

[c-sharp] view plaincopyprint?
  1. function Union:init(data)  
  2.     self:initTable()  
  3.     self.data = data  
  4.     local meta = {}  
  5.     meta.__index = function (table, key)  
  6.         if Union[key] ~= nil then  
  7.             return Union[key]  
  8.         else  
  9.             return self.data[key]  
  10.         end  
  11.     end  
  12.     meta.__newindex = function(table,key, value)  
  13.         self.data[key] = value  
  14.     end  
  15.     setmetatable(self, meta)  
  16. end  

3    103    3    3
4    103    4    4
4    103    103    103
4    104    104    104

 

2.错误的__newindex

[c-sharp] view plaincopyprint?
  1. function Union:init(data)  
  2.     self:initTable()  
  3.     self.data = data  
  4.     local meta = {}  
  5.     meta.__index = function (table, key)  
  6.         if Union[key] ~= nil then  
  7.             return Union[key]  
  8.         else  
  9.             return self.data[key]  
  10.         end  
  11.     end  
  12.     meta.__newindex = self.data  
  13.     setmetatable(self, meta)  
  14. end  

3    103    3    3
4    103    4    4
4    103    103    103
104    103    103    103

3.错误的__index

[c-sharp] view plaincopyprint?
  1. function Union:init(data)  
  2.     self:initTable()  
  3.     self.data = data  
  4.     local meta = {}  
  5.     meta.__index = function (table, key)  
  6.         if Union[key] ~= nil then  
  7.             return Union[key]  
  8.         else  
  9.             return data[key]  
  10.         end  
  11.     end  
  12.     meta.__newindex = function(table,key, value)  
  13.         self.data[key] = value  
  14.     end  
  15.     setmetatable(self, meta)  
  16. end  

3    103    3    3
4    103    4    4
4    103    4    103
4    104    4    104

 对象A在内部可以修改HP.外部对象只能访问对象A的HP,不能修改.

这东西其实可以用__index和__newindex来实现.

__index指向对象A,这样就可以访问;

__newindex重写,修改hp的话,就禁止.就可以完成他的需求.

下面给出简单的代码:

function cannotModifyHp(object)
    local proxy = {}
    local mt = {
        __index = object,
    __newindex = function(t,k,v)
        if k ~= "hp" then
        object[k] = v
        end
    end
    }
    setmetatable(proxy,mt)
    return proxy
end
  
object = {hp = 10,age = 11}
function object.sethp(self,newhp)
    self.hp = newhp
end
  
o = cannotModifyHp(object)
  
o.hp = 100
print(o.hp)
  
o:sethp(111)
print(o.hp)
  
object:sethp(100)
print(o.hp)
function cannotModifyHp(object)
    local proxy = {}
    local mt = {
        __index = object,
    __newindex = function(t,k,v)
        if k ~= "hp" then
        object[k] = v
        end
    end
    }
    setmetatable(proxy,mt)
    return proxy
end
object = {hp = 10,age = 11}
function object.sethp(self,newhp)
    self.hp = newhp
end
  
o = cannotModifyHp(object)
  
o.hp = 100
print(o.hp)
  
o:sethp(111)
print(o.hp)
  
object:sethp(100)
print(o.hp)

 

这里影响程序的不同结果是upvalue导致的。

由于一般程序中有可能动态改data。所以建议用function设置__index和__newindex,尤其注意各个不同函数中self指向的是什么对象

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/444997.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

leecode26 删除排序数组中的重复项

给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。 示例 1: 给定数组 nums [1,1,2…

MachineLearning(6)-Daviad Silver强化学习课程脉络整理

强化学习-Daviad Silver强化学习课程脉络整理1.lecture1 introduction1.1 强化学习简介1.2 强化学习类别1.3 强化学习的主要问题2.lecture2 Markov Decision Process2.1 MP,MRP,MDP2.2 Bellman Eqution--贝尔曼方程2.3 Bellman Eqution--贝尔曼期望方程2.4 最优策略2.5 最优值函…

lua的VS或者VC环境的搭建调试

安装完LuaForWindows_v5.1.4 打开vs tools->options->projects->directories executable files 选项添加lua安装以后的路径,我的是 C:\Program Files\Lua\5.1 include files选项添加lua include路径,我的是 C:\Program Files\Lua\5.1include library files 选项添…

leecode53 最大子序列和

给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。 示例: 输入: [-2,1,-3,4,-1,2,1,-5,4], 输出: 6 解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。 思路:…

在页游中LUA的应用(1)

通常,你希望在你的游戏开始的时候读取一些信息,以配置你的游戏,这些信息通常都是放到一个文本文件中,在你的游戏启动的时候,你需要打开这个文件,然后解析字符串,找到所需要的信息。 或许你认为这样就足够了,为什么还要使用Lua呢? 应用于“配置”这个目的,Lua提供给你…

Github(3)-本地文件管理

使用github 托管代码简单使用教程--本地文件管理1.基本概念2.本地文件管理2.1 git add2.2 git status2.3 git commit2.3 git log2.5 git reset --hard 版本回退2.6 git reflog2.7 git diff2.8 git checkout --file 工作区文件恢复2.9 git rm 删除版本库里的文件廖雪峰老师博文学…

linux 中阻塞与非阻塞 同步与异步

简单点说: 阻塞就是干不完不准回来, 非阻塞就是你先干,我先看看有其他事没有,完了告诉我一声。 我们拿最常用的send和recv两个函数来说吧。比如你调用send函数发送一定的Byte,在系统内部send做的工作其实只是把数据传输(Copy)到TCP/IP协议栈…

leecode62 不同路径

示例 1: 输入: m 3, n 2 输出: 3 解释: 从左上角开始,总共有 3 条路径可以到达右下角。 1. 向右 -> 向右 -> 向下 2. 向右 -> 向下 -> 向右 3. 向下 -> 向右 -> 向右 示例 2: 输入: m 7, n 3 输出: 28 思路:太过于简单&#xf…

数据库的查询优化建议整理

从大多数数据库应用系统的实例来看,查询操作在各种数据库操作中所占据的比重最大,而查询操作所基于的SELECT语句在SQL语句中又是代价最大的语句。 查询语句(SELECT)的优化建议 (1)、合理使用索引:where子句中变量顺序应与索引字键顺序相同。 如:create index test_idx…

Github(4)-远程操作

使用github 托管代码简单使用教程--远程操作3.连接本地仓库与远程仓库3.1 git clone 克隆实现链接3.2 git remote add origin4.远程操作4.1 git checkout -b 切换分支14.2 git branch 查看分支4.3 git merge 合并分支4.3.1 step1:切换成主分支4.3.2 step2&#xff1…

leetcode64 最小路径和

给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。 说明:每次只能向下或者向右移动一步。 示例: 输入: [ [1,3,1], [1,5,1], [4,2,1] ] 输出: 7 解释: 因为路径 1→3→1→1→1 的总…

online游戏服务器架构--网络架构

启动:父进程启动;子进程启动;网络架构。 每个父进程携带N个子进程,子进程负责处理业务逻辑和其它数据,而父进程只是将客户端的请求路由到各个子进程,路由的策略非常简单,父进程将请求包按照轮流…

online游戏服务器架构—用户登录数据组织 .

sprite_t类型的数据结构是核心数据结构,每一个登录用户对应一个,它的初始化在用户登录的时候,此后一直到用户退出或者离线一直保存在系统内存当中,在此过程中该sprite_t数据结构被保存在两个哈希表当中,一个是以用户的…

leetcode300 最长上升子序列

经典题&#xff0c;不解释&#xff0c;可以看我之前文章。 普通dp public class Solution {public int lengthOfLIS(int[] nums) {if (nums.length 0) {return 0;}int[] dp new int[nums.length];dp[0] 1;int maxans 1;for (int i 1; i < dp.length; i) {int maxval …

Github(5)-开源开发-常见错误

使用github 托管代码简单使用教程--开源开发-常见错误5. github开源开发6. 报错log6.1 fatal: remote origin already exists.6.2 There is no tracking information for the current branch.6.标签管理廖雪峰老师博文学习笔记&#xff1a;https://www.liaoxuefeng.com/wiki/89…

online游戏服务器架构--数据库及事件相关 .

Online服务器的第三部分就是数据层&#xff0c;send_request_to_db开始了数据层的处理逻辑&#xff1a; int send_request_to_db(int cmd, sprite_t* p, int body_len, const void* body_buf, uint32_t id)&#xff1b; 在该函数里首先以懒惰的方式连接数据库服务器&#xff…

leecode5 最长回文子串

给定一个字符串 s&#xff0c;找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。 示例 1&#xff1a; 输入: "babad" 输出: "bab" 注意: "aba" 也是一个有效答案。 示例 2&#xff1a; 输入: "cbbd" 输出: "bb"…

libxml解析xml文件的一些总结

libxml -- 解析 XML 文档XML 介绍&#xff1a;XML 和 DOMlibxml 介绍 数据类型 — xmlChar数据结构 创建 XML 文档解析 XML 文档修改 xml 文档Xpath — 处理大型 XML 文档libxml2 库函数要注意的函数读取 xml 文件xml 操作基本结构及其指针类型根节点相关函数 创建子节点相关函…

Linux(7)-正则表达式

正则表达式demo1:在某个文件中寻找命令seddemo2:寻找8位电话号码正则表达式&#xff1a;用来描述或者匹配某一系列符合某个句法队则的字符串或者单个字符串。最初正则表达式&#xff0c;出现在自动控制理论和形式化语言理论中。 Linux 中 find grep sed ls命令都支持正则表达式…

服务器端开发的一些建议

摘要: 本文作为游戏服务器端开发的基本大纲&#xff0c;是游戏实践开发中的总结。第一部分专业基础&#xff0c;用于指导招聘和实习考核&#xff0c; 第二部分游戏入门&#xff0c;讲述游戏服务器端开发的基本要点&#xff0c;第三部分服务端架构&#xff0c;介绍架构设计中的一…