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];
}
精彩评论