开发者

How to deal with double composition and inheritance?

I found this related question: How do I use composition with inheritance?

I would like to do the same with Objective-C, that is to say that a GenericView knows that its property obj is a GenericObject, and that a SpecializedView knows that the very same obj property is a SpecializedObject.

Here is an example that will be clearer:

//
//  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

As you see, I get an error at the end, because for SpecializedView the machine property is an ElectricalMachine, not a Toaster.

Thank you very much for your help!

Old Question

Here is the first version of my question, which was maybe too cryptic:

I have the following generic view:

@interface GenericView {
    GenericObject obj;
}

- (id)doSomething;

I also have the following specialized view:

@interface SpecializedView : GenericView {
}

- (id)doSomethingElse;

I have the following object:

@interface GenericObject {
}

- (id)plugIn;

and the following specialized object:

@interface SpecializedObject : GenericObject {
}

- (float)toastTime;

Let's say I want GenericView to handle GenericObject, and SpecializedView to handle the same object, knowing that it is SpecializedObject.

Let me explain by showing implementations:

GenericView doSomething

- 开发者_Go百科(id)doSomething {
    [obj plugIn];
}

SpecializedView doSomethingElse

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

I will get the following warning: 'GenericObject' may not respond to '-toastBread' and the following error: Incompatible types in assignement

Which is logical, since I have defined the type of obj as GenericObject. I want to be able to use methods from GenericObject in GenericView, and methods from SpecializedObject in SpecializedView. Is there a way to precise that obj has to be a GenericObject in GenericView to be handled, and has to be a SpecializedObject to be dealt with in SpecializedView, without adding a property? How would you do that?


Objective-C is a dynamically-typed language and methods are resolved at runtime, not compile time. If in SpecializedView, obj is in fact of an object of type SpecializedObject (even though it's declared as GenericObject), it will in fact respond to a toastBread message. The compiler will generate a warning but you can ignore it.

If SpecializedView may have both GenericObjects and SpecializedObjects, you can make sure that obj responds to toastBread using the respondsToSelector: message (inherited from NSObject):

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜