lua使用表模拟类和对象的实现过程中的一些问题

  lua中使用元表并指定元表的__index来模拟实现了类和对象,下面是一个我觉得比较好用的class方法,用来模拟实现类的继承,这个在我之前的博客中也有提及:

function class(classname, super)
    local cls

    if type(super) ~= "table" then
        super = nil
    end

    if super then
        cls = {}
        setmetatable(cls, {__index = super})
        cls.super = super
    else
        cls = {ctor = function() end}
    end

    cls.__cname = classname
    cls.__index = cls

    function cls.new(...)
        local instance = setmetatable({}, cls)
        instance.class = cls
        instance:ctor(...)
        return instance
    end
    return cls
end

  在这个class方法中,传入的第一个参数是类名,第二个参数是这个类要继承的类。在创建指定类名的新类中,使用__cname保存类名,并在新创建的类中实现了一个new方法,使用这个new方法可以创建一个对象,在new方法中会自动调用一个ctor方法,这个方法就是我们的默认方法。这个class方法实现了类的基本继承功能,而且还是可以根据需要自己拓展的。

  使用这个方法实现继承固然是比较方便的,但是也遇到了一些问题,准确地说不是这个class方法地问题,而是lua的问题。lua不论是模拟继承还是模拟类和对象的关系,都是使用设置元表并将元表的__index值设置为元表本身的方式实现的,这就会在使用过程中产生一个问题:多个类继承一个类或者一个类创建了多个对象(也就是多个表都有同一个元表)时,以一个类创建多个对象为例,如果在元表中声明了一些元素,在对象使用过程中对元素值进行了修改,那么你就会发现再次修改某个对象中的元素值时它实际修改的是类(元表)中的元素值,导致了所有对象的这个值一并改变了???但是我们知道实例对象之间的值应该是互不干扰的,这个问题也造成了一些诡异的bug。我在使用的过程中想办法规避这些问题,下面是我目前想到的一些办法的总结:

  1.一个类不要创建多个对象,只创建一个对象(强制单例),继承同样如此,一个类被继承了,就不要让其他类继承它;

  2.在创建对象时会调用ctor方法,那么在ctor方法中将类中声明的元素值重置(也就是在对象中将类中的元素全部复制以便,这样避免在使用中产生对象表中没有某个元素的情况,不会到类表中去寻找)

  3.在类中不声明任何元素,所有的元素都在ctor构造方法中使用self点出来的方式声明(也就是说,要用的元素在构造方法中去声明,在对象表中创建,类表中根本没有,实现对象之间的隔离)

原文地址:https://www.cnblogs.com/movin2333/p/14717035.html