Как бороться с двойной композицией и наследованием? - PullRequest
0 голосов
/ 30 октября 2009

Я нашел этот связанный вопрос: Как использовать композицию с наследованием?

Я хотел бы сделать то же самое с Objective-C, то есть GenericView знает, что его свойство obj является GenericObject, и что SpecializedView знает, что то же самое свойство obj SpecializedObject.

Вот пример, который будет более понятным:

//
//  Example.m

#import <UIKit/UIKit.h>

/* HEADER */

// Electrical Machine
@interface ElectricalMachine : NSObject {
}
- (void)plugIn;

@end

// Toaster
@interface Toaster : ElectricalMachine {
}
- (float)getThermostat;

@end

// GenericView
@interface GenericView : NSObject {
    ElectricalMachine *machine;
}
- (void)doSomethingGeneric;
@property (nonatomic, retain) ElectricalMachine *machine;

@end

//SpecializedView
@interface SpecializedView : GenericView {
}
- (void)doSomethingSpecialized;
@end


/* IMPLEMENTATION */

// GenericView
@implementation GenericView

@synthesize machine;

- (void)doSomethingGeneric {
    Toaster *toaster = [[Toaster alloc] init];
    [toaster plugIn];
    self.machine = toaster;
    [toaster release];
}

@end

// SpecializedView
@implementation SpecializedView

- (void)doSomethingSpecialized {
    /* ERROR HERE
     * Incompatible types in initialization
     * 'ElectricalMachine' may not respond to '-getThermostat'
     */
    float r = [machine getThermostat];
    r = r;
    // ...
}

@end

Как видите, в конце я получаю сообщение об ошибке, потому что для SpecializedView свойство машины является ElectricalMachine, а не Toaster.

Большое спасибо за помощь!

Старый вопрос

Вот первая версия моего вопроса, которая, возможно, была слишком загадочной:

У меня есть следующий общий вид:

@interface GenericView {
    GenericObject obj;
}

- (id)doSomething;

У меня также есть следующий специализированный вид:

@interface SpecializedView : GenericView {
}

- (id)doSomethingElse;

У меня есть следующий объект:

@interface GenericObject {
}

- (id)plugIn;

и следующий специализированный объект:

@interface SpecializedObject : GenericObject {
}

- (float)toastTime;

Допустим, я хочу, чтобы GenericView обрабатывал GenericObject, а SpecializedView обрабатывал тот же объект, зная, что это SpecializedObject.

Позвольте мне объяснить, показывая реализации:

GenericView doSomething

- (id)doSomething {
    [obj plugIn];
}

Специализированный просмотр doSomethingElse

- (id)doSomethingElse {
    // ERROR here
    float time = [obj toastTime];
}

Я получу следующее предупреждение: 'GenericObject' может не отвечать на '-toastBread' и следующая ошибка: Несовместимые типы в назначении

Что логично, поскольку я определил тип obj как GenericObject. Я хочу иметь возможность использовать методы из GenericObject в GenericView и методы из SpecializedObject в SpecializedView. Есть ли способ уточнить, что obj должен быть GenericObject в GenericView, который должен обрабатываться, и должен быть SpecializedObject для обработки в SpecializedView без добавления свойства? Как бы вы это сделали?

1 Ответ

0 голосов
/ 30 октября 2009

Objective-C - это язык с динамической типизацией, и методы разрешаются во время выполнения, а не во время компиляции. Если в SpecializedView, obj фактически является объектом типа SpecializedObject (даже если он объявлен как GenericObject), он фактически ответит на сообщение toastBread. Компилятор выдаст предупреждение, но вы можете его игнорировать.

Если SpecializedView может иметь и GenericObjects, и SpecializedObjects, вы можете убедиться, , что obj ответит на toastBread, используя сообщение respondsToSelector: (унаследовано от NSObject) :

if ([obj respondsToSelector:@selector(toastBread)]) {
    [obj toastBread];
}
...