Reputation: 20185
I need your help. Following problem in Objective-C:
// Robot.h
@protocol RobotProtocol <NSObject>
-(void)doWork;
@end
@interface Robot : NSObject
// Rob1 sublass of class Robot
// rob1.h
@interface Rob1 : Robot <RobotProtocol>
// rob1.m
@implementation
-(void)doWork
{
// print 'robot 1'
}
// Rob2 sublass of class Robot
// rob2.h
@interface Rob2 : Robot <RobotProtocol>
// rob2.m
@implementation
-(void)doWork
{
// print 'robot 2'
}
// Task.h
@interface Task : NSObject
{
Robot *rob;
}
// Task.m
@implementation
- (id)init
{
if ([super init]) {
rob = [[Rob1 alloc] init]; // or Rob2 !!
}
return self;
}
-(void)doSomething
{
[rob doWork]; // how to make sure, that this is implemented, depending on Rob1 or Rob2
}
How should Robot
and its subclasses be implemented, that Robot *rob
can be one of the subclasses of Robot rob1
, rob2
, ...
and the method doWork:(BOOL)val;
can be called? My first idea was to implement Robot
as an abstract class, but unfortunately there are no abstract classes in Objective-C...
At the moment I am using a protocol, but I am not confident. Because it is not sure, that doWork is implemented, the compiler complains about
'Robot' may not respond to 'doWork'
Thank you for your ideas.
Upvotes: 3
Views: 11462
Reputation: 23788
As many stated, there are no abstract classes in Objective-C. Personally I go for comments + runtime check. Code like this:
@interface Abstract : NSObject {
}
// Abstract method
- (Foo*)doSomething;
@end
@implementation Abstract
// Abstract method
- (Foo*)doSomething {
[_self doesntRecognizeSelector:_cmd];
return nil;
}
@end
If you really want to use something "abstract" and have compile time checks, I think you'll have to use protocols. To do so you need to slightly change your code. Particularly you should declare your variable as conforming to protocol, either id<RobotProtocol>
or Robot<RobotProtocol>*
depending on what better suits your needs:
// Task.h
@interface Task : Robot <RobotProtocol>
{
id<RobotProtocol> rob;
}
Upvotes: 1
Reputation: 587
Does whatever method is trying to call doWork know about the RobotProtocol protocol? You may need to import whatever header file contains it.
For what it's worth, the accepted way to do what you want is to just declare whatever the superclass is (Robot), declare and implement methods with empty bodies (possibly throwing an NSException if they aren't overwritten by a subclass) and create your subclass (SubRobot, or what have you). Protocols are more so different types of classes can implement a few known methods, not for use as de-facto abstract superclasses.
Upvotes: 0
Reputation: 42598
Protocols should work.
@protocol RobotProtocol <NSObject>
@required
- (void)doWork:(BOOL)flag;
@end
@interface Robot1 : NSObject <RobotProtocol>
@end
@implementation Robot1
- (void)doWork:(BOOL)flag
{
}
@end
Unit Test for Robot1
called though id<RobotProtocol>
- (void)testRobot
{
id<RobotProtocol> robot = [[Robot1 alloc] init];
[robot doWork:YES];
}
Update
After looking at your code, @interface Robot : NSObject
should be @interface Robot : NSObject <RobotProtocol>
. The thing is you don't need @interface Robot : NSObject <RobotProtocol>
at all. You can just use id<RobotProtocol>
. This is the name of your abstract class.
Upvotes: 8
Reputation: 6991
Objective-C does not have something called abstract classes like you have in java. Just create a superclass called Robot and subclass it.. you could potentially even block instancing the class by overriding init and immediately destroying itself ( though I am not too sure about the 'corectness' of such an approach.. )
In any case, it shouldn't be an issue.
Also a handy trick to figure out whether a certain object responds to a method is by using
if( [rob respondsToSelector:@selector(doWork:)] ) { [rob doWork:value]; }
this is often used in order to make methods in a protocol optional, so that you do not get errors at runtime when you call a method that does not exist for a given object.
Upvotes: 0
Reputation: 5173
I'm guessing you're trying to do something like this but without code it's hard to say...
//Robot.h
{
-(void)doWork:(BOOL)myBool
}
//Robot.m
{
-(void)doWork:(BOOL)myBool
{
if (myBool)
{
//do something
}
else
{
//do something else
}
}
}
//Task.h
{
#include"Robot.h"
}
//Task.m
{
Robot *rob = [[Robot rob] alloc] init];
[rob doWork:YES];
}
Upvotes: 0