游戏类的 Objective C 多态性

Posted

技术标签:

【中文标题】游戏类的 Objective C 多态性【英文标题】:Objective C Polymorphism for a Game Class 【发布时间】:2013-03-15 17:22:27 【问题描述】:

我的情况是我的应用中有几个不同的小游戏。游戏在表格视图中列出,当其中一个被选中时,我创建了相应的游戏对象。我需要游戏对象有一个共同的父类,这样我就可以做一些常见的事情,比如暂停和恢复。

我有一个具有通用 GameLayer 属性的通用 GameScene 类:

@interface GameScene : CCScene 



@property (nonatomic, strong) GameLayer* gameLayer;

但是,GameScene 的每个子类都有自己的 GameLayer 类型。例如,SuperMarioBros_GameScene 有一个 SuperMarioBros_GameLayer。当我初始化 SuperMarioBros_GameScene 时出现问题:

-(id) init

    if( (self = [super init])) 
        self.gameLayer = (SuperMarioBros_GameLayer*)[SuperMarioBros_GameLayer node];
        [self addChild: self.gameLayer];

        SuperMarioBros_InputLayer *inputLayer = [SuperMarioBros_InputLayer node];
        inputLayer.delegate = self.gameLayer; //ERROR (see below)
        [self addChild:inputLayer z:1 tag:2];
    
    return self;

通常每个游戏都会有一个输入层,它会向游戏层发送 UI 消息。我收到此错误:

Assigning to 'id <SuperMarioBros_FireDelegate> from incompatible type GameLayer*

我知道这是因为 SuperMarioBros_GameLayer 实现了&lt;SuperMarioBros_FireDelegate&gt;,但 GameLayer 没有。

所以我的问题是如何让 GameScene 类拥有可以是 GameLayer 的任何子类的多态属性?请记住,每种类型的 GameLayer 可能会根据其相应的输入层实现不同的协议?或者也许有更好的方法来解决这个问题?

同样,最终目标是能够从主游戏控制器发出调用,例如

[currentGameScene pause];

这又会做类似的事情:

[self.gameLayer pauseGameLoop];

【问题讨论】:

【参考方案1】:

SuperMarioBros_GameScene类的实现文件中,可以覆盖类扩展中gameLayer属性的属性声明:

@interface SuperMarioBros_GameScene ()
@property (nonatomic, strong) SuperMarioBros_GameLayer *gameLayer;
@end

那么您应该不会再收到编译器错误了。

这不会创建新的 getter 或 setter 函数(它们仍然在超类中调用),并且不会引入新的实例变量作为后备存储。它只告诉编译器self.gameLayer是这个实现文件中子类的一个实例。

【讨论】:

我大概有 75% 清楚这为什么有效,但它确实有效,而且很简单。

以上是关于游戏类的 Objective C 多态性的主要内容,如果未能解决你的问题,请参考以下文章

Objective-C继承与多态

Objective-C继承与多态

Objective-C多态:动态类型识别+动态绑定+动态加载

Objective-C的封装继承与多态

聊聊JSPatch的动态性原理

Objective-C中的继承与多态, Category, Extension