因为之前师父告诉咱ctor相当于构造函数,不熟悉lua模拟面向对象细节的咱用的时候感觉怪怪的,所以这里试着总结下,慢慢写。
首先看下源码:(function.lua)
function class(classname, super) local superType = type(super) local cls if superType ~= "function" and superType ~= "table" then superType = nil super = nil end if superType == "function" or (super and super.__ctype == 1) then -- inherited from native C++ Object cls = {} if superType == "table" then -- copy fields from super for k,v in pairs(super) do cls[k] = v end cls.__create = super.__create cls.super = super else cls.__create = super cls.ctor = function() end end cls.__cname = classname cls.__ctype = 1 function cls.new(...) local instance = cls.__create(...) -- copy fields from class to native object for k,v in pairs(cls) do instance[k] = v end instance.class = cls instance:ctor(...) return instance end else -- inherited from Lua Object if super then cls = {} setmetatable(cls, {__index = super}) cls.super = super else cls = {ctor = function() end} end cls.__cname = classname cls.__ctype = 2 -- lua cls.__index = cls function cls.new(...) local instance = setmetatable({}, cls) instance.class = cls instance:ctor(...) return instance end end return cls end
对于使用传入function方式继承cocos2dx类的自定义类如MainScene:(MainScene.lua)
local MainScene = class("MainScene", function() return display.newScene("MainScene") end)
function会成为__create变量的值,在new方法中调用,返回值为display.newScene("MainScene"),即:(display.lua)
function display.newScene(name) local scene = CCScene:create() scene:setNodeEventEnabled(true) scene:setAutoCleanupEnabled() scene.name = name or "<unknown-scene>" return scene end
CCScene:create()返回的对象,该对象由cocos2dx的工厂方法create创建,由cocos2dx的内存管理机制管理。
之后调用该对象的ctor方法,在官方demo中MainScene的ctor为自己添加了CCLabelTTF控件,这个在cocos2dx中更像是init方法的行为,而不是构造函数……
比较一下:(CCScene.cpp)
CCScene *CCScene::create() { CCScene *pRet = new CCScene(); if (pRet && pRet->init()) { pRet->autorelease(); return pRet; } else { CC_SAFE_DELETE(pRet); return NULL; } }
而init方法做了控件等的初始化和附加等操作:(HelloWorld.cpp,注释略)
bool HelloWorld::init() { if ( !CCLayer::init() ) { return false; } CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize(); CCPoint origin = CCDirector::sharedDirector()->getVisibleOrigin(); CCMenuItemImage *pCloseItem = CCMenuItemImage::create( "CloseNormal.png", "CloseSelected.png", this, menu_selector(HelloWorld::menuCloseCallback)); pCloseItem->setPosition(ccp(origin.x + visibleSize.width - pCloseItem->getContentSize().width/2 , origin.y + pCloseItem->getContentSize().height/2)); CCMenu* pMenu = CCMenu::create(pCloseItem, NULL); pMenu->setPosition(CCPointZero); this->addChild(pMenu, 1); CCLabelTTF* pLabel = CCLabelTTF::create("Hello World", "Arial", TITLE_FONT_SIZE); pLabel->setPosition(ccp(origin.x + visibleSize.width/2, origin.y + visibleSize.height - pLabel->getContentSize().height)); this->addChild(pLabel, 1); CCSprite* pSprite = CCSprite::create("HelloWorld.png"); pSprite->setPosition(ccp(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y)); this->addChild(pSprite, 0); return true; }
c++中的new主要做了:
调用构造函数,调用init方法为scene\layer等添加控件,进入内存管理机制
lua中的此时的new主要做了:
调用原create方法进入内存管理机制,调用ctor方法为scene\layer等添加控件,同时可以用来初始化当前“对象”的“成员变量”
结论:
目前自己认为,这种场合ctor可以用来对当前“对象”的“成员变量”进行初始化,这个行为和构造函数相似;同时生成并附加给场景\层所需的控件,这个行为与init方法相似,同时做了两件事。需要自己注意的是ctor执行前,即初始化成员变量前,当前对象已经是(可以当做)由cocos2dx工厂方法create出来的参与了内存管理的对象了。
对于在cocos2dx中通过create来创建并使用的类/子类,在quick中可通过new来创建并使用。