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中创建字段安全的对象的更多相关文章

  1. Java中创建(实例化)对象的五种方式

    Java中创建(实例化)对象的五种方式1.用new语句创建对象,这是最常见的创建对象的方法. 2.通过工厂方法返回对象,如:String str = String.valueOf(23); 3.运用反 ...

  2. 在Spring应用中创建全局获取ApplicationContext对象

    在Spring应用中创建全局获取ApplicationContext对象 1.需要创建一个类,实现接口ApplicationContextAware的setApplicationContext方法. ...

  3. 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 ...

  4. 按要求编写Java应用程序。 (1)创建一个叫做机动车的类: 属性:车牌号(String),车速(int),载重量(double) 功能:加速(车速自增)、减速(车速自减)、修改车牌号,查询车的载重量。 编写两个构造方法:一个没有形参,在方法中将车牌号设置“XX1234”,速 度设置为100,载重量设置为100;另一个能为对象的所有属性赋值; (2)创建主类: 在主类中创建两个机动车对象。 创建第

    package com.hanqi.test; public class jidongche { private String chepaihao;//车牌号 private int speed;// ...

  5. 编写Java应用程序。首先,定义一个Print类,它有一个方法void output(int x),如果x的值是1,在控制台打印出大写的英文字母表;如果x的值是2,在 控制台打印出小写的英文字母表。其次,再定义一个主类——TestClass,在主类 的main方法中创建Print类的对象,使用这个对象调用方法output ()来打印出大 小写英文字母表。

    package zuoye; public class print1 { String a="abcdefghigklmnopqrstuvwxyz"; String B=" ...

  6. (1)创建一个叫做机动车的类: 属性:车牌号(String),车速(int),载重量(double) 功能:加速(车速自增)、减速(车速自减)、修改车牌号,查询车的载重量。 编写两个构造方法:一个没有形参,在方法中将车牌号设置“XX1234”,速 度设置为100,载重量设置为100;另一个能为对象的所有属性赋值; (2)创建主类: 在主类中创建两个机动车对象。

    package a; public class Jidongche { private String chepaihao; private int chesu; private double zaiz ...

  7. 首先,定义一个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 ...

  8. .编写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 ...

  9. 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 ...

随机推荐

  1. Python3选择支持非ASCII码标识符的缘由

    原文在: PEP 3131 -- Supporting Non-ASCII Identifiers. Python2并不支持非ASCII码标识符. PEP的全称是Python Enhancement ...

  2. Microsoft Dynamics CRM 9.0 OP 版本 移动端

    本次OP 版本做了架调整,新的移动端基本可以满足客户需求,其内容自己可配置选择,满足了一般企业的应用处理. 具体操作如下: 1.登录APP选择应用(我使用手机浏览器) 2.打开默认应用,现在就一个木得 ...

  3. DNS协议总结

    1.DNS用于根据域名返回ip地址. 2.一般情况下,DNS-server是通过在UDP协议与客户端之间交互的,UDP端口号是53. 特别注意.DNS有时会使用TCP 53端口与客户端进行交互,所以, ...

  4. The packaging and installation process of Android programs

    D:\android\adt-bundle-windows-x86-20131019\sdk\platform-tools工具的路径. 安卓工程经过eclipse编译然后通过aapt工具打包生成一个. ...

  5. Kotlin入门(10)七十二变的输入参数

    上一篇文章介绍了Kotlin对函数的基本用法,包括函数的定义.输入参数的声明.输出参数的声明等等,这些足够对付简单的场合了.当然了,倘若一门新语言仅仅满足于这些雕虫小技,那也实在没什么前途.既然Kot ...

  6. Apktool(1)——Apktool的安装

    Apktool是google提供的apk的编译工具,有了它就可以做很多事情.比如获取apk的源码,apk汉化,对手机rom包做一些美化. 首先来看看apktool的安装(配置): 以下内容主要翻译字A ...

  7. 关键字提取算法TF-IDF和TextRank(python3)————实现TF-IDF并jieba中的TF-IDF对比,使用jieba中的实现TextRank

    关键词:    TF-IDF实现.TextRank.jieba.关键词提取数据来源:    语料数据来自搜狐新闻2012年6月—7月期间国内,国际,体育,社会,娱乐等18个频道的新闻数据    数据处 ...

  8. bs4爬虫入门

    # -*- coding: utf-8 -*- """ Created on Fri Nov 16 13:35:33 2018 @author: zhen "& ...

  9. 解决eclipse启动慢

    每次启动eclipse时都要等待半分钟左右,对于追求效率的程序员来说,等待每一秒都是一种折磨,出于高效开发的精神,这个问题必须解决掉.方案如下: ①在工具栏中的help中找到about eclipse ...

  10. 薛兆丰吴军何帆曾鸣万维刚李笑来罗永浩等得到APP专栏作者的书23本

    最近看了何帆的<大局观>,是他在得到APP的专栏文章的精选.顺便整理以下最近两三年内看过的得到APP其他专栏与课程作者的得到精选文集和他们写过的其他的书共23本. 薛兆丰 4星|<薛 ...