Chapter 16_1 Class
一个类就是一个创建对象的模具。对于一些基于原型的语言,对象是没有“类型”的,而是每个对象都有一个原型(prototype).
原型也是一种常规的对象。当其他对象(类的实例)遇到一个未知操作时,原型会先查找它。这种语言要创建一个类,只需要创建一个专用作其他对象的原型。
类和原型都是一种组织对象间共享行为的方式。
在Lua中,可以用继承实现原型。如果有两个对象a和b,要让b作为a的原型:
setmetatable(a, {__index = b})
在此之后,a就会在b中查找所有它没有的操作。将b称为是对象a的类,只不过是术语上的一个变化。
回到上面的Account例子中,为了创建更多与Account行为类似的账号,可以让这些新对象从Account行为中继承这些操作。
具体做法是使用__index元方法。可以用一项小优化,则无须创建一个额外的table作为账户对象的元表。而是使用Account table自身作为元素:
function Account:new(o)
o = o or {} --如果用户没有提供,就创建一个空表
setmetatable(o , self )
self.__index = self
return o
end
当调用Account:new时,self就等于Account。因此可以直接用Account代替self。
当引入类继承时,使用self则会更为准确。
a = Account:new(balance = )
a:deposit(100.00)
当创建新账号时,a会将Account作为元表,当调用a:deposit(100.00)时,就是调用了a.deposit(a, 100.00).
当Lua无法在table a中找到条目deposit时,会进一步搜索元表的__index条目。
getmetatable(a).__index.deposit(a, 100.00)
a的元表是Account,Account.__index也是Account。因此,上面的表达式可以简化为:
Account.deposit(a , 100.00)
结果为Lua调用了原来的deposit函数,但传入a作为self参数。因此新账号a从Account继承了deposit函数。
继承不仅可以作用于方法,也可以作用于所有其他在新账户中没有的字段。
比如上面的balance field。如果在创建新账户时没有提供balance的初值,那么它就会继承这个默认值。
b = Account:new()
print(b. balance) --> 0
在b上调用deposit时,self就是b,相当于:
b.balance = b.balance + v
在第一次调用deposit时,对b.balance的求值结果为0,然后一个初值被赋予了b.balance。
后续对b.balance的访问就不会再涉及到__index元方法了,因为此时b已有自己的balance字段。
以上内容来自:《Lua程序设计第二版》和《Programming in Lua third edition 》
Chapter 16_1 Class的更多相关文章
- Modern C++ CHAPTER 2(读书笔记)
CHAPTER 2 Recipe 2-1. Initializing Variables Recipe 2-2. Initializing Objects with Initializer Lists ...
- Android Programming: Pushing the Limits -- Chapter 7:Android IPC -- ApiWrapper
前面两片文章讲解了通过AIDL和Messenger两种方式实现Android IPC.而本文所讲的并不是第三种IPC方式,而是对前面两种方式进行封装,这样我们就不用直接把Aidl文件,java文件拷贝 ...
- Android Programming: Pushing the Limits -- Chapter 7:Android IPC -- Messenger
Messenger类实际是对Aidl方式的一层封装.本文只是对如何在Service中使用Messenger类实现与客户端的通信进行讲解,对Messenger的底层不做说明.阅读Android Prog ...
- [转]第四章 使用OpenCV探测来至运动的结构——Chapter 4:Exploring Structure from Motion Using OpenCV
仅供参考,还未运行程序,理解部分有误,请参考英文原版. 绿色部分非文章内容,是个人理解. 转载请注明:http://blog.csdn.net/raby_gyl/article/details/174 ...
- 《深入理解计算机系统》 Chapter 7 读书笔记
<深入理解计算机系统>Chapter 7 读书笔记 链接是将各种代码和数据部分收集起来并组合成为一个单一文件的过程,这个文件可被加载(货被拷贝)到存储器并执行. 链接的时机 编译时,也就是 ...
- 《Linux内核设计与实现》Chapter 3 读书笔记
<Linux内核设计与实现>Chapter 3 读书笔记 进程管理是所有操作系统的心脏所在. 一.进程 1.进程就是处于执行期的程序以及它所包含的资源的总称. 2.线程是在进程中活动的对象 ...
- PRML Chapter 2. Probability Distributions
PRML Chapter 2. Probability Distributions P68 conjugate priors In Bayesian probability theory, if th ...
- PRML Chapter 1. Introduction
PRML Chapter 1. Introduction 为了防止忘记,要把每章的重要内容都记下来,从第一章开始 2012@3@28 今天又回去稍微翻了一下第一章内容,发现第一次看的时候没有看透,每次 ...
- MathType 插入定义的chapter and section break后无法隐藏
每一章标题后面插入一个“Next Section Break”,这样定稿后各章文件组合为总文件后,方程编号会自动递增,如果已经插入了默认的“Equation Chapter 1 Section 1”, ...
随机推荐
- kali客户端攻击
浏览器攻击 browser_autpwn2 (BAP2) mkdir /test 为接受响应的服务器创建目录 use auxiliary/server/browser_autopwn2 set ...
- HDU 1329 Hanoi Tower Troubles Again!(乱搞)
Hanoi Tower Troubles Again! Problem Description People stopped moving discs from peg to peg after th ...
- c++中宽字节表示
1.C++语言中_T Visual C++里边定义字符串的时候,用_T来保证兼容性,VC支持ascii和unicode两种字符类型,用_T可以保证从ascii编码类型转换到unicode编码类型的时候 ...
- 【IE6的疯狂之三】IE6 3像素BUG的实例
问题:2列布局.左列固定,右列液态我需要做一个布局.2列,左边列固定宽度.右边列使用剩余宽度.整体宽度不固定,这样不管在17 还是19的屏幕上,左边列始终宽度不变,右边列宽度始终占据剩余宽度.但是我写 ...
- servlet就实现在线用户表
在学习servlet的过程中,学习了如何用servlet实现在线用户表. 只有服务器处于开机状态才会有在线用户表的存在,在服务器关机的情况下自然就不存在在线用户表的说法:所以,楼主认为在线用户表的信息 ...
- laravel sum 多个字段
laravel中怎么实现下面的SQL select sum('profit'),sum('order_count') from pro where......; 参考 self::where('id' ...
- maven打包配置
maven打包配置,到底要打包哪些文件,如何配置?? <build> <finalName>weatherAdminSys</finalName> <plug ...
- echart+jquery+json统计TP数据
由于工作需要,需要统计交易数据的TP50,TP90,TP95,TP99.采用的前端技术是jquery+json+echart. 一.TP定义(谷歌) Calculating TP is very si ...
- python 基础学习-总结1
1.Python 简介 易学易懂,语法简单 不需编译,即可运行 比其他语言更简洁 不需要管理内存 1.1 什么是Python? python 是由Guido.van.Rossum于1989年始创,其根 ...
- python获取
def anc():pass print anc.__name__ def timeit(func): def run(*argv): print "this function name i ...