id确认协议,但实现在哪里?

Tea*_*App 5 protocols objective-c ios

这可能是一个天真的问题,但我感觉有点失落.我在Apple文档中阅读了关于协议的iOS开发人员指南,但是没有多大意义.让我以尽可能短的方式解释我的困境.

可以说我的协议如下,

@protocol MyProtocol<NSObject>
- (void)someMessage;
@end
Run Code Online (Sandbox Code Playgroud)

而且在我的代码中,我声明了一个这样的变量,

id<MyProtocol> someVar;
Run Code Online (Sandbox Code Playgroud)

到目前为止这么好,但是someVar我们将在哪里实施-(void) someMessage;


注意:我有这样的知识,接口的已定义函数的实现应该在实现该接口的类中.这种理解来自Java,在Java中,很明显知道哪个对象来自哪个类以及该类实现的接口.但是上面的Objective C方式让我困惑:(.


vig*_*o24 7

当你写:

id<MyProtocol> someVar
Run Code Online (Sandbox Code Playgroud)

你只是声明"someVar"将是任何类的对象,但是这个类将遵循协议MyProtocol.

因此,代码中会有一些实例化someVar的点.此时someVar将与一个类相关联.该类必须满足MyObject协议.请注意,编译器将尽力在出现问题时向您发出警告,例如,如果将此对象强制转换为某个不遵循协议的类,例如假设您的协议定义了一个名为"protocolMethod"的方法,那么:

[(NSArray *)someVar protocolMethod]
Run Code Online (Sandbox Code Playgroud)

将生成编译器警告("NSArray可能不响应protocolMethod").

当然,您永远不会受到运行时错误的保护:因此,如果在运行时将someVar创建为不满足协议的类,则对协议方法的任何调用都将引发异常.


Bol*_*ock 5

简单地说,Objective-C协议在概念和代码方面与Java接口大致相似。

如果将Java变量声明为接口类型,则意味着它可以接受实现该接口的任何对象。在Objective-C中,id变量表示任何指针类型,因此id<MyProtocol>表示指向采用的对象的任何指针MyProtocol,并且在某种意义上类似于Java接口类型声明。

在Java中,您可以在一个类中实现接口方法,然后声明该类以实现接口。同样,在Objective-C中,您可以在一个类中实现协议方法,并让该类采用该协议。

这是Java与Objective-C之间的代码比较(同样,这只是两个相似概念的宽松比较):

爪哇

public interface MyInterface {
    void someMethod();
}

public class MyClass implements MyInterface {
    public void someMethod() {
        System.out.println("Some method was called");
    }
}

public class Main {
    public static void main(String[] args) {
        // Any class that implements MyInterface can be
        // assigned to this variable
        MyInterface someVar = new MyClass();
        someVar.someMethod();
    }
}
Run Code Online (Sandbox Code Playgroud)

目标C

@protocol MyProtocol <NSObject>
- (void)someMessage;
@end

@interface MyClass : NSObject <MyProtocol>
- (void)someMessage;
@end

@implementation MyClass

- (void)someMessage {
    NSLog(@"Some message was sent");
}

@end

int main(int argc, const char *argv[]) {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    // Any class that adopts MyProtocol can be
    // assigned to this variable
    id<MyProtocol> someVar = [[MyClass alloc] init];
    [someVar someMessage];

    [someVar release];
    [pool drain];
    return 0;
}
Run Code Online (Sandbox Code Playgroud)