一个类就是一个创建对象的模具。对于一些基于原型的语言,对象是没有“类型”的,而是每个对象都有一个原型(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. November 12th 2016 Week 46th Saturday

    Never love anyone who treats you like you are ordinary. 请爱那些爱你的人. Don't waste your limited energy on ...

  2. 回文质数 Prime Palindromes

    题目描述 因为151既是一个质数又是一个回文数(从左到右和从右到左是看一样的),所以 151 是回文质数. 写一个程序来找出范围[a,b](5 <= a < b <= 100,000 ...

  3. DB2的基础指令 学习笔记

    =======DB2基础指令======= 1.打开数据库db2 connect to 数据库名;2.查看数据库中有哪些表db2 list tables ;3.查看数据库中的表结构db2 descri ...

  4. 【转】delphi 保存到txt文件

    procedure TForm1.btn1Click(Sender: TObject); var astr: string; sList: TStrings; path: string; begin ...

  5. Dylans loves numbers

    Problem Description Who is Dylans?You can find his ID in UOJ and Codeforces. His another ID is s1451 ...

  6. Linux lsof命令详解和使用示例【转】

    所以如传输控制协议 (TCP) 和用户数据报协议 (UDP) 套接字等,系统在后台都为该应用程序分配了一个文件描述符,无论这个文件的本质如何,该文件描述符为应用程序与基础操作系统之间的交互提供了通用接 ...

  7. NSRange:NSMakeRange

    NSRange:NSMakeRange(6, cardNo.length - 10) [cardNo stringByReplacingCharactersInRange:NSMakeRange(6, ...

  8. Quartz简单实例

    Quartz中提供了两种触发器,分别是CronTrigger和SimpleTrigger. 1. SimpleTrigger 每隔若干毫秒来触发纳入进度的任务. 2. CronTrigger 在特定& ...

  9. TinyXML用法小结

    TinyXML用法小结 1.      介绍 Tinyxml的官方网址:http://www.grinninglizard.com 官方介绍文档:http://www.grinninglizard.c ...

  10. C# WebBrowser禁止F5刷新

    在用写一个桌面软件的过程中,用到webbrowser实现界面.这时有一个禁止webbrowser通过f5按键进行刷新的要求.本着边做边学的原则,本菜查了一下百度,原来这么简单,代码如下: this.w ...