简体   繁体   English

目标C子类化:这合适吗?

[英]Objective C Subclassing: Is this proper?

So I'm working on an iPad game using the cocos2d framework. 因此,我正在使用cocos2d框架开发iPad游戏。

My game requires different buildings to be spawned at the beginning of a "level". 我的游戏要求在“关卡”开始时生成不同的建筑物。 The user gets to choose which buildings they want to use. 用户可以选择他们要使用的建筑物。

An important functionality here is that different buildings will perform different actions when pressed. 这里的一项重要功能是,不同的建筑物在被按下时将执行不同的动作。

I have a parent class that looks something like this: 我有一个看起来像这样的父类:

BaseBuilding.h

@interface BaseBuilding : NSObject {
    CGRect _hitBox;
    NSString *_name;

    CCSprite *_sprite;
    int _identifier;
    int _health;

    int _coolDownDuration;
}

@property (atomic, retain) CCSprite *sprite;
@property (atomic, assign) int identifier;
@property (atomic, assign) int health;

- (void) onBuildingPressed;
- (id) initWithName:(NSString*)baseName;
- (id) initBuilding;
- (CGRect) hitBox;
- (void) sustainDamage;

So most of my buildings are very similar. 所以我的大多数建筑物都很相似。 Each building has their own initBuilding method which overrides the parent. 每个建筑物都有自己的initBuilding方法,该方法将覆盖父级。 The initBuilding method calls the super initWithName method which then looks up a plist with information about that building (sprite name, etc). initBuilding方法将调用super initWithName方法,该方法随后会在plist中查找有关该建筑物的信息(精灵名称等)。

Each building also has their own onBuildingPressed method, which also overrides the parent method. 每个建筑物还具有自己的onBuildingPressed方法,该方法还将覆盖父方法。 This is very important functionality. 这是非常重要的功能。

The part that I'm having trouble with: 我遇到的问题:

I want to spawn the buildings based on what the player selects. 我想根据玩家的选择生成建筑物。 What I'm currently doing is something like this: 我目前正在做的事情是这样的:

BaseBuilding *building;

switch (choice) {
    case 1:
        building = [BuildingX alloc];
        [building initBuilding];
        break;
    case 2:
        building = [BuildingY alloc];
        [building initBuilding];
        break;
    case 3:
        building = [BuildingZ alloc];
        [building initBuilding];
        break;
}

return building;

Since BuildingX, BuildingY, BuildingZ are all subclasses of BaseBuilding, initBuilding does call the correct method. 由于BuildingX,BuildingY和BuildingZ都是BaseBuilding的子类,因此initBuilding确实会调用正确的方法。

Later on I can call [rightBuilding onBuildingPressed]; 稍后我可以打电话给[rightBuilding onBuildingPressed]; and it works as expected. 并且它按预期工作。

BuildingX has a removeAmmo method that the other buildings don't have, so I have to do this to call it: [(BuildingX*)centerBuilding removeAmmo] . BuildingX具有其他建筑物所没有的removeAmmo方法,因此我必须调用它: [(BuildingX*)centerBuilding removeAmmo]

Is this proper, or this a better way of doing this? 这是正确的方法还是更好的方法?

The only thing that I notice is that, if you have many subclasses - provided that all subclasses have some alphabetical order - you do it faster and more elegantly by getting a class object according to the value of choice: 我唯一注意到的是,如果您有许多子类(假设所有子类都按字母顺序排列),则可以根据选择的值获取类对象,从而更快,更优雅地完成此工作:

NSString* className= [NSString stringWithFormat: @"Building%c",'X'-1+choice];
Class class= NSClassFromString(className);
BaseBuilding* building= [[class alloc] initBuilding];

But this is just a matter of style and rapidity (writing the code, I mean). 但这只是样式和速度的问题(我是说编写代码)。 Your method is perfectly fine and there's nothing wrong with it. 您的方法非常好,没有任何问题。

You can verify the class at run time to guarantee there's no room for error here like so: 您可以在运行时验证类,以确保这里没有错误的余地,如下所示:

if ( [centerBuilding respondsToSelector:NSSelectorFromString(@"removeAmmo")] ) {
    [centerBuilding performSelector:NSSelectorFromString(@"removeAmmo"];
}

Seems logical to me. 对我来说似乎合乎逻辑。 I don't know if it's stylish, the snobs can determine that for you. 我不知道它是否时尚,势利的人可以为您确定。 If it works, it works. 如果可行,则可行。 I don't see the point in fixing things that aren't broken. 我认为修复未损坏的内容没有意义。

Yes, it's correct. 是的,这是正确的。 But: 但:

1) If you are casting all your subclasses to the parent class, and you need to use a particular method of your subclass, then it's useless casting to the right subclass ONLY in certain circumstances. 1)如果将所有子类都转换为父类,并且需要使用子类的特定方法,那么仅在某些情况下,将其转换为正确的子类是无用的。 Try to make the removeAmmo a base method... 尝试将removeAmmo设为基本方法...

or 要么

2) make your building subclass calling the removeAmmo method from its inside, and declare the removeAmmo method in a category 2)使建筑物子类从内部调用removeAmmo方法,并在类别中声明removeAmmo方法

From an external point of view, the BaseClass has not the removeAmmo method, so it's not logic to declare a public method which could be called only re-casting your object to a specific subclass. 从外部角度来看,BaseClass没有removeAmmo方法,因此声明一个公共方法(调用该方法只能将您的对象重新投射到特定的子类)不是逻辑。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM