zoukankan      html  css  js  c++  java
  • 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 = 0)
    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 》

  • 相关阅读:
    设计模式与23种设计模式的简单介绍
    一文读懂C++ Vector在算法竞赛中的常见用法
    一文读懂C++ String类在算法竞赛中的常见用法
    GO语言的单元测试与性能测试
    变量提升和函数提升及二者优先级
    闭包
    读《你不知道的JavaScript 中》-异步【3】Promise
    js数组方法-改变原数组和不改变原数组
    读《你不知道的JavaScript 中》-异步【2】回调
    组合类算法问题
  • 原文地址:https://www.cnblogs.com/daiker/p/5882409.html
Copyright © 2011-2022 走看看