在lua中创建字段安全的对象
lua萌新,刚刚学习和使用不到一个月。有不对的地方,还望各路大神不吝赐教。
lua中可以用table来模拟对象,但table是可以任意增加键值的。在对象模拟中,暂且也叫它为字段(field)吧。如果在面向对象中,你定义了一个对象,可以在对象以外的地方随意改动这个对象的字段,访问不存在的字段,你想象一下这有多恐怖?比如你定义了一个Vector3{float x = 0; float y = 0; float z = 0;} 我在外面某处加一个float t = 1; 当你在创建并引用这对象的时候,你就懵逼了,t是什么鬼?又或者你new 一个对象 vector,然后去取一个值,本来里面没有 t 这个字段,vector.t 给你返回一个空值,你是不是又懵逼了?到底是里面有这个字段值为空,还是压根就没这个字段?嗯? 感觉太不可控了。
那么,有没有办法让它可控一点呢?有的。利用元表的__index 和__newindex,具体如下代码:
local Vector3 = {}
function Vector3:new()
local v3 =
{
x = , -- Note:这个值不能为nil,不然找不到这个字段
y = ,
z = ,
}
setmetatable(v3, self)
self.__index =
function(self, key)
error("Vector3类型中没有定义字段:" .. key, )
end
self.__newindex =
function(self, key, value)
error("Vector3类型中没有定义字段:" .. key, )
end
return v3
end
local v = Vector3:new()
v.x =
--v.t = 3
print(v.x)
print(v.y)
--print(v.t)
上面的代码输出:

但当你尝试把v.t = 3 的注释去掉的话,就报错了:

尝试去掉print(v.t) 的注释的话,也会报错:

这样就可以确保这个结构的安全,主要体现在不能在外部随意对它修改。
--------------------2017.08.20更新
下面是升级版本的,初始化的时候可以传入参数,为初始化提供了方便。还提供了一个ToString()方法。
local Vector3 = {}
function Vector3:new(x0, y0, z0)
local v3 =
{
x = x0 or ,
y = y0 or ,
z = z0 or ,
ToString = function(self)
return "(" .. self.x .. "," .. self.y .. "," .. self.z .. ")"
end
}
setmetatable(v3, self)
self.__index =
function(self, key)
error("Vector3类型中没有定义字段:" .. key, )
end
self.__newindex =
function(self, key, value)
error("Vector3类型中没有定义字段:" .. key, )
end
return v3
end
local v = Vector3:new(, , )
v.x =
print(v.x)
print(v.y)
print("Vector3 v = " .. v:ToString())
--------------------2017.08.22更新
上面的方法依然会有问题,就是当给字段赋值为空的时候,相当于把字段删了,字段就消失了。不能再次访问或者赋值。下面是再次升级的版本:
local Vector3 = {}
function Vector3:new(x0, y0, z0)
--合法字段和默认值
local v3_field =
{
x = ,
y = ,
z = ,
}
--初始化字段
local v3 =
{
x = x0 or v3_field.x,
y = y0 or v3_field.y,
z = z0 or v3_field.z,
}
setmetatable(v3, self)
self.__tostring = function(self)
return "(" .. self.x .. "," .. self.y .. "," .. self.z .. ")"
end
self.__index =
function(self, key)
local valid = false
for k, v in pairs(v3_field) do
if key == k then
valid = true
result = rawget(v3, key) or v --如果值为空,返回v3_field中的默认值
return result
end
end
if not valid then
error("Invalid field in Vector3: " .. key, )
end
end
self.__newindex =
function(self, key, value)
print("set newindex")
local valid = false
for k, v in ipairs(v3_field) do
if key == k then
valid = true
rawset(v3, key, value)
return
end
end
if not valid then
error("Invalid field in Vector3: " .. key, )
end
end
return v3
end
local v = Vector3:new(, , )
v.x =
print(v.x)
v.y = nil
print(v.y)
print("Vector3 v = " .. tostring(v))
输出为:

这样即使是字段被赋值为nil,依然可以访问并重新赋值。
在lua中创建字段安全的对象的更多相关文章
- Java中创建(实例化)对象的五种方式
Java中创建(实例化)对象的五种方式1.用new语句创建对象,这是最常见的创建对象的方法. 2.通过工厂方法返回对象,如:String str = String.valueOf(23); 3.运用反 ...
- 在Spring应用中创建全局获取ApplicationContext对象
在Spring应用中创建全局获取ApplicationContext对象 1.需要创建一个类,实现接口ApplicationContextAware的setApplicationContext方法. ...
- 11.按要求编写Java应用程序。 (1)创建一个叫做机动车的类: 属性:车牌号(String),车速(int),载重量(double) 功能:加速(车速自增)、减速(车速自减)、修改车牌号,查询车的载重量。 编写两个构造方法:一个没有形参,在方法中将车牌号设置“XX1234”,速 度设置为100,载重量设置为100;另 一个能为对象的所有属性赋值; (2)创建主类: 在主类中创建两个机动车对象。
package java1; public class Che { //属性 public String nub; public int speed; public double weight ; C ...
- 按要求编写Java应用程序。 (1)创建一个叫做机动车的类: 属性:车牌号(String),车速(int),载重量(double) 功能:加速(车速自增)、减速(车速自减)、修改车牌号,查询车的载重量。 编写两个构造方法:一个没有形参,在方法中将车牌号设置“XX1234”,速 度设置为100,载重量设置为100;另一个能为对象的所有属性赋值; (2)创建主类: 在主类中创建两个机动车对象。 创建第
package com.hanqi.test; public class jidongche { private String chepaihao;//车牌号 private int speed;// ...
- 编写Java应用程序。首先,定义一个Print类,它有一个方法void output(int x),如果x的值是1,在控制台打印出大写的英文字母表;如果x的值是2,在 控制台打印出小写的英文字母表。其次,再定义一个主类——TestClass,在主类 的main方法中创建Print类的对象,使用这个对象调用方法output ()来打印出大 小写英文字母表。
package zuoye; public class print1 { String a="abcdefghigklmnopqrstuvwxyz"; String B=" ...
- (1)创建一个叫做机动车的类: 属性:车牌号(String),车速(int),载重量(double) 功能:加速(车速自增)、减速(车速自减)、修改车牌号,查询车的载重量。 编写两个构造方法:一个没有形参,在方法中将车牌号设置“XX1234”,速 度设置为100,载重量设置为100;另一个能为对象的所有属性赋值; (2)创建主类: 在主类中创建两个机动车对象。
package a; public class Jidongche { private String chepaihao; private int chesu; private double zaiz ...
- 首先,定义一个Print类,它有一个方法void output(int x),如果x的值是1,在控制台打印出大写的英文字母表;如果x的值是2,在 控制台打印出小写的英文字母表。其次,再定义一个主类——TestClass,在主类 的main方法中创建Print类的对象,使用这个对象调用方法output ()来打印出大 小写英文字母表。
package lianxi; public class Print_1 { int x; Print_1(int x) { this.x = x; } void outPut() { String ...
- .编写Java应用程序。首先,定义一个Print类,它有一个方法void output(int x),如果x的值是1,在控制台打印出大写的英文字母表;如果x的值是2,在 控制台打印出小写的英文字母表。其次,再定义一个主类——TestClass,在主类 的main方法中创建Print类的对象,使用这个对象调用方法output ()来打印出大 小写英文字母表。
package com.homework.zw; //类Print部分 public class Print1 { int x; void output() { if(x==1) { for(int ...
- 7.编写Java应用程序。首先,定义一个Print类,它有一个方法void output(int x),如果x的值是1,在控制台打印出大写的英文字母表;如果x的值是2,在 控制台打印出小写的英文字母表。其次,再定义一个主类——TestClass,在主类 的main方法中创建Print类的对象,使用这个对象调用方法output ()来打印出大 小写英文字母表。
package com.bao; public class Print1 { int x; void output() { if(x==1) { System.out.println("AB ...
随机推荐
- Java字符串占位符(commons-text)替换(转载)
Java字符串占位符(commons-text)替换 https://blog.csdn.net/varyall/article/details/83651798 <dependency> ...
- Lightning框架示例 - 动态建立Lightning组件
动态建立Lightning组件 组件化前端开发是Lightning框架的优点之一.在进行Lightning应用开发时,我们可以将组件进行嵌套.引用,从而实现模块的封装和重用,提高开发效率. 组件的嵌套 ...
- loadrunner 场景设计-手工场景设计
场景设计-手工场景设计 by:授客 QQ:1033553122 概述 通过选择需要运行的脚本,分配运行脚本的负载生成器,在脚本中分配Vuser来建立手工场景 手工场景就是自行设置虚拟用户的变化,主要是 ...
- logcat use
将已经存在的工程导入到eclipse步骤: ①:首先复制当前工程所在的路径. ②:然后在eclipse,右键->Import->General->Existing Projects ...
- JavaScript大杂烩6 - 理解JavaScript中的this
在JavaScript开发中,this是很常用的一个关键字,但同时也是一个很容易引入bug的一个关键字,在这里我们就专门总结一下页面中可能出现的this关键字(包括几种在其他页面文件中出现的this) ...
- 微信小程序-下拉事件(onPullDownRefresh)不触发
1.app.json 没有配置 "window": { /* 其他配置信息 */ "enablePullDownRefresh":true } 2.scroll ...
- win7计划任务报该任务映像己损坏或己篡改
目录 win7计划任务报该任务映像己损坏或己篡改 前言 解决方案 排查损坏的计划任务映像 win7计划任务报该任务映像己损坏或己篡改 文:铁乐与猫 2018-9-20 前言 win7下想自定义一些计划 ...
- git 创建本地仓库、远程仓库,上传项目
1.在本地想创建git仓库的地方创建本地仓库 首先右键打开 Git Bash Here,如果没有,请先安装git,下载地址:https://git-scm.com/downloads git init ...
- 从列表和实例来了解python迭代器
什么是迭代器?它是一个带状态的对象,在你调用next()方法的时候返回容器中的下一个值,任何实现了__iter__和__next__()(python2中实现next())方法的对象都是迭代器,__i ...
- spark-Scala
一.spark的特点 1.快速的 2.容易使用的 3.通用的 4.开放的 二.spark组件 sparkCore sparkSQL sparkStreaming MLibmachielearning ...