Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Abstract class in Objective-C

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.

like image 341
Michael Dorner Avatar asked Jan 21 '26 11:01

Michael Dorner


2 Answers

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.

like image 147
Jeffery Thomas Avatar answered Jan 23 '26 07:01

Jeffery Thomas


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;
}
like image 32
SergGr Avatar answered Jan 23 '26 06:01

SergGr



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!