一个类就是一个创建对象的模具。对于一些基于原型的语言,对象是没有“类型”的,而是每个对象都有一个原型(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. 51nod1092(lcs简单运用/dp)

    题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1092 题意:中文题诶- 思路: 解法1:最坏的情况就是在原字 ...

  2. docker容器安全

    title: docker容器安全 tags: Docker,容器,安全策略 grammar_cjkRuby: true --- Docker容器的安全性 1.安全策略-Cgroup 1.限制Cpu ...

  3. 3、href和src的区别

    href:将现在的页面连接到新的页面 src:将需要引用的东西添加到现在的页面 <a href="mailto:youremailaddress@host.com">C ...

  4. Ecstore安装篇-2.单机部署【linux】

    单机部署实施-linux 单机部署实施-linux author :James,jimingsong@vip.qq.com since :2015-03-02 系统环境需求 软件来源 底层依赖 1. ...

  5. 简单的jquery ajax文件上传功能

    /* * 图片上传 * 注意如果不加processData:false和contentType:false会报错 */ function uploadImage(image) { var imageF ...

  6. winform开线程,避免页面假死

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...

  7. Codeforces Round #346 (Div. 2) B Qualifying Contest

    B. Qualifying Contest 题目链接http://codeforces.com/contest/659/problem/B Description Very soon Berland ...

  8. 安装TensorFlow的步骤

    安装步骤: 1.安装虚拟机: 2.安装liunx系统: 3.安装TensorFlow. 1.安装虚拟机:虚拟机的版本是不能太低的.我使用的是:VMware-workstation-full-12.0. ...

  9. android从assets读取文件的方法

    因为开发需要,经常要从工程的assets文件夹里面读取文件,现在贴一个方法以作记录: private void getFromAssets(String fileName, ArrayList< ...

  10. 为Array 添加indexOf

    为array赋予属性 if (!Array.prototype.indexOf) { Array.prototype.indexOf = function (elt /*, from*/) { var ...