发现的lua小技巧记录--在:方法中使用self的技巧

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

在lua中定义了一个全局的方法class用于模仿编译型语言的类继承的功能,使用class(类名,继承类)声明一个类,第二个参数可选(可以不继承任何类),在类中实现ctor方法作为构造方法,使用类名.new()的方式创建类对象。下面是应用过程中出现的问题:

1)创建一个类,继承自其他类

SingleGamePanel = class("SingleGamePanel",BasePanel)

2)在其他类中创建这个类的对象

self.View = SingleGamePanel.new()

3)调用类中定义的方法

--调用View中的方法
self.View:InstantiateAChess(position,id)

4)被调用的方法,注意方法中实例化了一个游戏物体,在添加监听事件和发送通知时都会连续使用:调用成员方法,这个调用就出现了一个问题:我是用的是对象调用的方法,那么self指对象,但是在添加监听事件时使用冒号调用了其他方法,添加的监听事件函数中self就不再指对象了,不能使用self,那么使用类SingleGamePanel可以吗?也不可以,因为在lua中对象和类都是表,本质上类是对象的元表,在对象中做的操作和类中做的操作是分离的,只是对象中找不到的元素到类中去找,如方法最后存储棋子的步骤,就存储在对象中,要是使用类表去调用这个存储的棋子是访问不到的。问题就产生了,我在监听事件函数中要使用对象中定义的函数等怎么办?

--在指定的position位置实例化给定id对应的棋子
function SingleGamePanel:InstantiateAChess(position,id)--使用一个表存储棋子
    local chess = {}

    --实例化棋子
    chess.gameObject = AssetBundleManager:LoadRes("chesspiece",chessDic[id].name,typeof(GameObject))
    chess.transform = chess.gameObject.transform
    --设置实例出来的棋子的位置
    chess.transform:SetParent(local.chessFather,false)
    chess.transform.localPosition = Tools:PositionCastToLocal(position)

    --棋子需要存储自己的位置
    chess.position = position

    --为标识棋子状态的图片赋值
    chess.selectedImg = chess.transform:Find(ControlNames.CHESS_SELECTED_IMAGE).gameObject
    chess.selectedImg:SetActive(false)
    chess.canBeEatImg = chess.transform:Find(ControlNames.CHESS_CAN_BE_EAT_IMAGE).gameObject
    chess.canBeEatImg:SetActive(false)
    chess.lastImg = chess.transform:Find(ControlNames.LAST_CHESS_IMAGE).gameObject
    chess.lastImg:SetActive(false)

    --为棋子上的Button添加监听事件
    chess.gameObject:GetComponent(typeof(Button)).onClick:AddListener(function()
        if chess.canBeEatImg.activeInHierarchy then
            GameFacade:GetInstance():SendNotification(NotificationNames.EAT_CHESS,MoveChessBody.new(SingleGamePanel.nowSelectedPosition,chess.position))
            SingleGamePanel:CancelAllStatus()
        elseif not chess.selectedImg.activeInHierarchy then
            chess.selectedImg:SetActive(true)
            GameFacade:GetInstance():SendNotification(NotificationNames.CHESS_TOUCHED,chess.position)
        end
    end)

    --将棋子存入总表中
    local.chesses[position:ToString()] = chess
end

5)解决方法:在方法中都首先使用一个临时变量转存self,接下来临时变量就可以在方法中随意使用,它始终指向对象。

--在指定的position位置实例化给定id对应的棋子
function module:InstantiateAChess(position,id)
    local temp = self
    --使用一个表存储棋子
    local chess = {}

    --实例化棋子
    chess.gameObject = AssetBundleManager:LoadRes("chesspiece",chessDic[id].name,typeof(GameObject))
    chess.transform = chess.gameObject.transform
    --设置实例出来的棋子的位置
    chess.transform:SetParent(temp.chessFather,false)
    chess.transform.localPosition = Tools:PositionCastToLocal(position)

    --棋子需要存储自己的位置
    chess.position = position

    --为标识棋子状态的图片赋值
    chess.selectedImg = chess.transform:Find(ControlNames.CHESS_SELECTED_IMAGE).gameObject
    chess.selectedImg:SetActive(false)
    chess.canBeEatImg = chess.transform:Find(ControlNames.CHESS_CAN_BE_EAT_IMAGE).gameObject
    chess.canBeEatImg:SetActive(false)
    chess.lastImg = chess.transform:Find(ControlNames.LAST_CHESS_IMAGE).gameObject
    chess.lastImg:SetActive(false)

    --为棋子上的Button添加监听事件
    chess.gameObject:GetComponent(typeof(Button)).onClick:AddListener(function()
        if chess.canBeEatImg.activeInHierarchy then
            GameFacade:GetInstance():SendNotification(NotificationNames.EAT_CHESS,MoveChessBody.new(temp.nowSelectedPosition,chess.position))
            temp:CancelAllStatus()
        elseif not chess.selectedImg.activeInHierarchy then
            chess.selectedImg:SetActive(true)
            GameFacade:GetInstance():SendNotification(NotificationNames.CHESS_TOUCHED,chess.position)
        end
    end)

    --将棋子存入总表中
    temp.chesses[position:ToString()] = chess
end
原文地址:https://www.cnblogs.com/movin2333/p/14694620.html