一个类就是一个创建对象的模具。对于一些基于原型的语言,对象是没有“类型”的,而是每个对象都有一个原型(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的更多相关文章

  1. Modern C++ CHAPTER 2(读书笔记)

    CHAPTER 2 Recipe 2-1. Initializing Variables Recipe 2-2. Initializing Objects with Initializer Lists ...

  2. Android Programming: Pushing the Limits -- Chapter 7:Android IPC -- ApiWrapper

    前面两片文章讲解了通过AIDL和Messenger两种方式实现Android IPC.而本文所讲的并不是第三种IPC方式,而是对前面两种方式进行封装,这样我们就不用直接把Aidl文件,java文件拷贝 ...

  3. Android Programming: Pushing the Limits -- Chapter 7:Android IPC -- Messenger

    Messenger类实际是对Aidl方式的一层封装.本文只是对如何在Service中使用Messenger类实现与客户端的通信进行讲解,对Messenger的底层不做说明.阅读Android Prog ...

  4. [转]第四章 使用OpenCV探测来至运动的结构——Chapter 4:Exploring Structure from Motion Using OpenCV

    仅供参考,还未运行程序,理解部分有误,请参考英文原版. 绿色部分非文章内容,是个人理解. 转载请注明:http://blog.csdn.net/raby_gyl/article/details/174 ...

  5. 《深入理解计算机系统》 Chapter 7 读书笔记

    <深入理解计算机系统>Chapter 7 读书笔记 链接是将各种代码和数据部分收集起来并组合成为一个单一文件的过程,这个文件可被加载(货被拷贝)到存储器并执行. 链接的时机 编译时,也就是 ...

  6. 《Linux内核设计与实现》Chapter 3 读书笔记

    <Linux内核设计与实现>Chapter 3 读书笔记 进程管理是所有操作系统的心脏所在. 一.进程 1.进程就是处于执行期的程序以及它所包含的资源的总称. 2.线程是在进程中活动的对象 ...

  7. PRML Chapter 2. Probability Distributions

    PRML Chapter 2. Probability Distributions P68 conjugate priors In Bayesian probability theory, if th ...

  8. PRML Chapter 1. Introduction

    PRML Chapter 1. Introduction 为了防止忘记,要把每章的重要内容都记下来,从第一章开始 2012@3@28 今天又回去稍微翻了一下第一章内容,发现第一次看的时候没有看透,每次 ...

  9. MathType 插入定义的chapter and section break后无法隐藏

    每一章标题后面插入一个“Next Section Break”,这样定稿后各章文件组合为总文件后,方程编号会自动递增,如果已经插入了默认的“Equation Chapter 1 Section 1”, ...

随机推荐

  1. 转:Spark User Defined Aggregate Function (UDAF) using Java

    Sometimes the aggregate functions provided by Spark are not adequate, so Spark has a provision of ac ...

  2. .NET中的SqlBulkCopy类用法

    在开发过程中,经常会遇到向数据库插入大量数据的情况,那么如果是百万条数据,一条条的插入实在是太慢了,所以就有了SqlBulkCopy类. 本文中我将示范SqlBulkCopy类的不同应用. 以下面三张 ...

  3. CodeForces 687B Remainders Game

    数论. 如果$x$不唯一,假设存在两个解,较大的为${x_1}$,较小的为${x_2}$. 那么, $\left\{ {\begin{array}{*{20}{c}}{{x_1}\% {c_i} = ...

  4. 【JS】倒计时

    描述: 先要链接jquery.js,这样写法可以直接放JS文件运行. //放在图片里定位的倒计时 //顶图里面定位才使用的代码 document.writeln("<style> ...

  5. Uploadify 上传后的文件删除,上传队列无法更新问题

    1. 定义一个上传限制数量 var uploadLimit = 3; 2. 点击页面的删除图片成功后,将uploadLimit++操作 3. 通过uploadify的settings方式重置上传限制数 ...

  6. myeclipse连接数据库oracle

    package xsl; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStat ...

  7. ORACLE ORDER BY用法总结

    order by后面的形式却比较新颖(对于我来说哦),以前从来没看过这种用法,就想记下来,正好总结一下ORDER BY的知识. 1.ORDER BY 中关于NULL的处理 缺省处理,Oracle在Or ...

  8. 万恶的tileMap

    先吐槽下.. 本来,我们准备用tileMap来做地图的,但发现一个问题,就是tileMap层中不能添加cc.Sprite,这导致了tileMap只适合做2D平面没有遮挡的游戏,并且主角是不能有效率的进 ...

  9. 两个队列实现一个栈,剑指offer P59

    public class StackByQueue { private LinkedList<String> queue1; private LinkedList<String> ...

  10. MUI——页面的创建、显示、关闭

    一.打开子页面 mui.init({ subpages:[{ url:your-subpage-url,//子页面HTML地址,支持本地地址和网络地址 id:your-subpage-id,//子页面 ...