3

我需要你的帮助。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
}

应该如何Robot实现及其子类,可以Robot *rob是 Robot 的子类之一rob1,并且可以调用该方法?我的第一个想法是实现为抽象类,但不幸的是,Objective-C 中没有抽象类......rob2...doWork:(BOOL)val;Robot

目前我正在使用协议,但我没有信心。因为不确定是否实现了 doWork,所以编译器会抱怨

“机器人”可能不会响应“doWork”

谢谢你的想法。

4

5 回答 5

8

协议应该有效。

@protocol RobotProtocol <NSObject>
@required
- (void)doWork:(BOOL)flag;
@end

@interface Robot1 : NSObject <RobotProtocol>
@end

@implementation Robot1
- (void)doWork:(BOOL)flag
{
}
@end

Robot1被调用的单元测试id<RobotProtocol>

- (void)testRobot
{
    id<RobotProtocol> robot = [[Robot1 alloc] init];
    [robot doWork:YES];
}

更新

查看您的代码后,@interface Robot : NSObject应该是@interface Robot : NSObject <RobotProtocol>. 问题是你根本不需要@interface Robot : NSObject <RobotProtocol>。你可以只使用id<RobotProtocol>. 这是您的抽象类的名称。

于 2012-12-07T18:58:49.363 回答
1

正如许多人所说,Objective-C 中没有抽象类。我个人去评论+运行时检查。像这样的代码:

@interface Abstract : NSObject {
}

// Abstract method
- (Foo*)doSomething;

@end

@implementation Abstract

// Abstract method
- (Foo*)doSomething {
  [_self doesntRecognizeSelector:_cmd];
  return nil;
}

@end

如果您真的想使用“抽象”的东西并进行编译时检查,我认为您将不得不使用协议。为此,您需要稍微更改代码。特别是您应该将您的变量声明为符合协议,id<RobotProtocol>或者Robot<RobotProtocol>*取决于更适合您的需求:

// Task.h
@interface Task : Robot <RobotProtocol>
{
    id<RobotProtocol> rob;
}
于 2012-12-07T19:10:07.097 回答
0

我猜你正在尝试做这样的事情但是没有代码很难说......

//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];
}
于 2012-12-07T18:31:43.723 回答
0

Objective-C 没有像 java 中那样的抽象类。只需创建一个名为 Robot 的超类并将其子类化..您甚至可以通过覆盖 init 并立即销毁自身来阻止实例化该类(尽管我不太确定这种方法的“正确性”..)

无论如何,这不应该是一个问题。

确定某个对象是否响应方法的一个方便技巧是使用

if( [rob respondsToSelector:@selector(doWork:)] ) { [rob doWork:value]; }

这通常用于使协议中的方法成为可选方法,以便在调用给定对象不存在的方法时不会在运行时出错。

于 2012-12-07T18:32:26.203 回答
0

尝试调用 doWork 的任何方法都知道 RobotProtocol 协议吗?您可能需要导入包含它的任何头文件。

对于它的价值,做你想做的事情的公认方法是只声明超类是什么(机器人),声明和实现具有空主体的方法(如果它们没有被子类覆盖,可能会抛出 NSException)并创建你的子类(SubRobot,或者你有什么)。协议更多的是不同类型的类可以实现一些已知的方法,而不是用作事实上的抽象超类。

于 2012-12-07T19:00:18.213 回答