在抽象的Objective-C类中使用常量?

时间:2012-02-04 01:13:34

标签: objective-c macos cocoa oop inheritance

首先,让我澄清一下,我知道你不能在Objective-C中拥有实际的抽象类。当我说抽象时,我的意思是我没有创建该类的任何实例,而只是将它用作继承的基类。

我的抽象类包含一个NSInteger。从此抽象类继承的所有类都需要使用此整数。一旦设置,NSInteger将永远不会被更改。 NSInteger的值虽然会因派生类而异。因为它永远不会被改变,所以我想制作变量const。但事情是,如果我使它成为const,我将不得不在实例化时设置值。因此,我必须在基本抽象类中设置值 - 但是我不能根据它存在的派生类来调整值。

我意识到这很难理解所以我创建了一些基本的伪代码。我使用NSString作为示例,但在我的程序中它是一个NSInteger:

Class animal: const NSString soundItMakes = "Sound" //the constant integer
//since soundItMakes is const I have to set it upon instantiation even though it doesn't make sense in the base class

Class dog: animal //derives from animal. Needs to change the const soundItMakes to fit a dog however since it was already set in animal, the base class, I can't really change it

Class cat: animal //derives from animal. Needs to change the const soundItMakes to fit cat however since it was already set in animal, the base class, I can't really change it.

我不想从基类中删除变量,而是将它放在每个派生类中,也不想让它变为非常量。有没有人看到这个解决方案?我意识到这是令人困惑的,所以如果需要更多信息,请随时询问。

我在Mac OS X Snowleopard中使用Xcode 3.2.6中的Cocoa。

3 个答案:

答案 0 :(得分:5)

通常我会用方法而不是ivar来解决这个问题。

@interface Animal : NSObject
+ (NSString *)soundItMakes;
@end

@implementation Animal
+ (NSString *)soundItMakes {
  NSAssert(NO, @"Abstract");
}
@end

@implementation Dog
+ (NSString *)soundItMakes {
  return @"bark";
}

答案 1 :(得分:3)

首先:在这种情况下,我可能只使用Animal协议。

第二:如果你真的想要一个类的变量,这里有一种方法(你可以适应你正在使用的编译器版本):

@interface MONAnimal : NSObject
{
@private
  int animalCode;
  NSString * soundItMakes;
}

// designated initializer -- treat as protected
- (id)initWithAnimalCode:(int)inAnimalCode soundItMakes:(NSString *)soundItMakes;

... just don't declare setters for animalCode or soundItMakes!

@end

然后你会说:

@interface MONMoonBear : MONAnimal
@end

@implementation MONMoonBear

- (id)init
{
  return [super initWithAnimalCode:MONAnimalCode_MoonBear soundItMakes:@"Eating Garlic and Berries"];
}

@end

还有一些空白要填补 - 但这是推动一种方法的方向。

答案 2 :(得分:1)

使soundItMakes方法或在子类中重写的@property(readonly)。如果每个班级的价值不同,你别无选择,只能在每个班级重新定义。

// Animal.h
@interface Animal : NSObject
- (NSString *)soundItMakes;
@end

// Animal.m 
@implementation Animal
- (NSString *)soundItMakes
{
    // Throw exception, assert, etc.
    // This will force you to implement the subclass
    return (nil);
}

// Cat.h
@interface Cat : Animal
@property(readonly) NSString *soundItMakes;
@end

// Cat.m
@implementation Cat
@synthesize soundItMakes = _soundItMakes;

- (Cat *)init {
   NSString * const soundMade = @"Meow";

    self = [super init];
    if (self != nil)
        _soundItMakes = soundMade;
    return (self);
}
@end