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のサブクラスの1つである可能性があり、メソッドを呼び出すことができる、Robotおよびそのサブクラスをどのように実装する必要がありますか?私の最初のアイデアは抽象クラスとして実装することでしたが、残念ながら、Objective-Cには抽象クラスがありません...Robot *robrob1rob2...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 に答える