在 点击打开链接 这里看到一篇关于如何实现委托机制的文章,感觉有点意思,由于这篇文章只是讲了个思路,所以我自己实践了一下,写了一个demo。
实现委托机制demo的情景描述:
LayerA是一个层,里面有个sprite,一旦A被初始化,这个sprite就会执行一个action;LayerB是另一个层。我在LayerB中加入了LayerA,但是要等到A中的那个sprite的action执行完毕后,B再立刻执行另外一个方法。
问题来了,我怎么在LayerB中知道LayerA中的sprite的action执行完了,那么解决的方法就是使用委托机制。
下面直接通过我的demo进行讲解。
(1)首先创建一个VirtualClassC类,里面有一个虚函数。
class VirtualClassC
{
public:
//虚函数
virtual void actionFinished(){};
};
(2)接着创建LayerA,这个类继承CCLayer,并且有一个VirtualClassC类实例。 LayerA.h
#ifndef __delegate__LayerA__
#define __delegate__LayerA__
#include <iostream>
#include "VirtualClassC.h"
#include "cocos2d.h"
USING_NS_CC;
class LayerA :public CCLayer
{
public:
virtual bool init();
CREATE_FUNC(LayerA);
VirtualClassC *delegate_;
void callBack();
};
#endif /* defined(__delegate__LayerA__) */
LayerA.cpp
#include "LayerA.h"
bool LayerA::init()
{
if (!CCLayer::init()) {
return false;
}
//在LayerA层中添加一个sprite
CCSprite *pSprite = CCSprite::create("Icon.png");
CCSize wSize = CCDirector::sharedDirector()->getWinSize();
pSprite->cocos2d::CCNode::setPosition(wSize.width/2, wSize.height/2);
this->addChild(pSprite);
//让这个sprite执行一个动作序列
CCSequence *action = CCSequence::create(CCRotateBy::create(0.5, 360),CCCallFunc::create(this, callfunc_selector(LayerA::callBack)),NULL);
pSprite->runAction(action);
return true;
}
void LayerA::callBack()
{
if (delegate_) {
delegate_->actionFinished();
}
}
(3)最后,创建LayerB,这个类继承 VirtualClassC类和CCLayer类。
Layer.h
#ifndef __delegate__LayerB__
#define __delegate__LayerB__
#include <iostream>
#include "VirtualClassC.h"
#include "LayerA.h"
#include "cocos2d.h"
USING_NS_CC;
//
class LayerB:public VirtualClassC,public CCLayer
{
public:
virtual bool init();
static cocos2d::CCScene* scene();
CREATE_FUNC(LayerB);
virtual void actionFinished();
//假如A中action完毕后,B要去执行下面的方法
void doNext();
};
#endif /* defined(__delegate__LayerB__) */
Layer.cpp
#include "LayerB.h"
bool LayerB::init()
{
if ( !CCLayer::init() )
{
return false;
}
CCSize wSize = CCDirector::sharedDirector()->getWinSize();
LayerA *layerA = LayerA::create();
layerA->delegate_ = this;
layerA->setPosition(0, 0);
this->addChild(layerA);
CCLabelTTF *label = CCLabelTTF::create("LayerB", "Arial", 24);
label->setPosition(ccp(wSize.width/2, 80));
this->addChild(label);
return true;
}
CCScene* LayerB::scene()
{
// 'scene' is an autorelease object
CCScene *scene = CCScene::create();
// 'layer' is an autorelease object
LayerB *layer = LayerB::create();
// add layer as a child to scene
scene->addChild(layer);
// return the scene
return scene;
}
void LayerB::actionFinished()
{
doNext();
}
void LayerB::doNext()
{
CCLog("LayerA中sprite的acton已经结束");
}
(4)在程序启动的时候
// create a scene. it's an autorelease object
CCScene *pScene = LayerB::scene();
// run
pDirector->runWithScene(pScene);
"LayerA中sprite的acton已经结束"。
下面对于这个委托机制解释一下(结合OC中的委托机制):
VirtualClassC类中定义了一个虚函数,这个函数相当于就是委托方法;
LayerB继承了这个类,那么就要实现这个类中的虚函数,也即实现了委托方法;
LayerA中定义了一个VirtualClassC类实例,而且在LayerB的init方法中:layerA->delegate_ =this;即将LayerA中的委托对象指定为LayerB。
委托实现再理解:函数调用时,发生动态绑定。
我们知道:基类类型的指针或引用可以指向或引用基类类型对象,或者派生类类型对象。
那么:
1、通过基类类型指针或者引用指向了派生类对象,然后对函数调用
2、所调用函数为虚函数,派生类重写了该虚函数。
这个时候会发生的函数的函数调用是在运行期间才知道的,调用的不是基类版本的函数,而是派生类中的函数,所以是动态绑定。这就是动态多态性了。(静态多态性是函数重载)
在这个例子中:
1、首先定义一个基类VirtualClassC,其中有一个虚函数(基类相当于一个委托协议,虚函数相当于委托方法,但还未实现);
2、然后 LayerA 有一个该基类 VirtualClassC 的实例指针(public),使用这个指针调用VirtualClassC 中的虚函数,即调用委托方法(LayerA 相当于委托者,基类实例指针相当于委托实例,委托实例调用委托方法);
3、最后 LayerB 继承基类VirtualClassC,成为其子类,重写虚函数,并且创建 LayerA 实例,将 LayerA 中的 VirtualClassC 实例指针指向自己(this)(LayerB 相当于被委托者,需要实现委托方法)。
4、这样的效果是:在 LayerA 中 VirtualClassC 实例调用的是 LayerB 中重写的虚函数(委托方法)。这样就完成了委托的过程。