2012-02-04 2 views
2

Прежде всего, позвольте мне уточнить, что я знаю, что вы не можете иметь фактические абстрактные классы в Objective-C. Когда я говорю абстрактное, я имею в виду, что я не создаю никаких экземпляров класса, но просто использую его как базовый класс для наследования.Использование констант в абстрактных классах 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. 

Я не хочу, чтобы удалить переменную из базового класса и вместо того, чтобы положить его в каждом производном классе я не хочу, чтобы он непостоянен. Кто-нибудь видит решение этого? Я понимаю, что это сбивает с толку, поэтому, если требуется дополнительная информация, не стесняйтесь спрашивать.

Я использую Cocoa в Xcode 3.2.6 в Mac OS X Snowleopard.

+2

Почему бы просто не определить свойство readonly на вашем суперклассе, тогда каждый подкласс может реализовать метод getter, чтобы вернуть то, что им нужно. Это было бы каноническим способом OO, чтобы сделать это, я думаю, если я полностью не упустил вашу точку зрения. –

+0

Почему он должен оставаться переменной? Что мешает вам сделать метод, который возвращает его? – zneak

ответ

5

Обычно я обращался к этому методом, а не с ivar.

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

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

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

Отлично, спасибо. – fdh

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 
+1

Обратите внимание, что 'const NSString *' не имеет смысла. Вы имеете в виду 'NSString * const'. 'NSString' неизменен по своей природе, поэтому первый ничего не делает. Последнее препятствует переназначению 'soundMade' другому объекту, что вы на самом деле имеете в виду. –

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 

Есть еще несколько пробелов для заполнения, но это толкает направление одного подхода.

+0

+1 Это хороший подход в некоторых случаях (я обычно использую метод класса, но этот подход имеет свои применения). Более важным ответом от этого ответа является предположение о том, что 'Animal' является' @ protocol'. Это часто забытое решение. –

+0

+1 к твоему тоже - я бы добавил, что если бы ты не избил меня :) – justin

Смежные вопросы