非正式协议在Objective-C?

时间:2010-01-05 23:59:05

标签: objective-c

我想知道是否有人可以解释Objective C中的非正式协议?我尝试在苹果文档和其他一些书籍上理解它,但我的脑子仍在旋转,所以如果有人可以用例子来解释,我将非常感激。

感谢。

7 个答案:

答案 0 :(得分:59)

正如Jonnathan所说,非正式协议通常是在NSObject上声明的类别,没有相应的实现(最常见的是 - 在NSObject上提供了虚拟实现的罕见协议)。

从10.6开始(在iPhone SDK中),不再使用此模式。具体来说,在10.5(及之前)中声明如下:

@interface NSObject(NSApplicationNotifications)
- (void)applicationWillFinishLaunching:(NSNotification *)notification;
...
@interface NSObject(NSApplicationDelegate)
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender;
...

现在声明为:

@protocol NSApplicationDelegate <NSObject>
@optional
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender;
...
- (void)applicationWillFinishLaunching:(NSNotification *)notification;
...

也就是说,非正式协议现在被声明为@protocol,并带有一堆@optional方法。

在任何情况下,非正式协议都是方法声明的集合,您可以选择实现方法来更改行为。通常,但并非总是如此,方法实现是在委托的上下文中提供的(表视图的数据源必须实现一些必需的方法,并且可以选择性地实现一些其他方法)。

答案 1 :(得分:9)

非正式协议的一个常见例子是定义回调。假设您使用的库允许您在后台下载某些内容。该库允许您注册完成后要调用的回调对象。

- (void)download:(NSURL*)url whenComplete:(id)callback

下载完成后,它将在您的回调对象上调用特定方法:

- (void)downloadComplete:(NSURL*)url

当然,无法保证您的回调对象实际上实现了此方法。非正式协议使用类别在NSObject上提供这些方法的简单实现。因此,系统中的所有对象都将响应downloadComplete:方法,但默认情况下它们不会响应该方法。覆盖downloadComplete:方法的类可以提供更多有用的功能。

到目前为止,您可以使用正式协议完成同样的事情。但是,非正式协议允许您使用可选方法。实现正式协议的类必须为协议中的每个方法提供实现。实现非正式协议的类可以省略任何方法的实现 - 它已经从NSObject继承了实现。

自Objective-C 2.0以来,正式协议可以包含可选方法。此外,Apple可能正在逐渐摆脱新API的非正式协议 - UIAccelerometerDelegate是一种正式的协议。

答案 2 :(得分:5)

我们通过对类别声明中的方法进行分组来定义informal protocol

@interface NSObject ( MyXMLSupport )
- initFromXMLRepresentation:(NSXMLElement *)XMLElement;
- (NSXMLElement *)XMLRepresentation;
@end

Informal protocol通常被声明为NSObject类的类别,因为它广泛关联 方法名称包含任何继承自NSObject的类。

因为所有类都继承自根类, 方法不限于继承层次结构的任何部分。 (也可以宣布 informal protocol作为另一个类的类别,将其限制为继承层次结构的某个分支, 但没有理由这样做。)

当用于声明协议时,类别接口没有相应的实现。代替, 实现该协议的类在它们自己的接口文件中再次声明这些方法并定义它们 以及其实现文件中的其他方法。

答案 3 :(得分:5)

非正式协议通过类别向对象添加可选方法的方法。

因此可能出现一个疑问

如果协议本身有任何可选方法,它会成为非正式协议吗?

答案是否定的。

如果方法是在协议中声明的,并且它被认为符合类而没有使用类别那么它就是正式协议

注意:

协议中的可选方法在目标c 2.0中引入,因此在此之前,目的是通过非正式协议I.e通过类别实现的。

<强>分类

这是一种语言级别的功能,可以替代子类别继承。

我希望它对此有所了解......

答案 4 :(得分:4)

所有非正式协议都是某个类(通常为NSObject)的类别,它声明了协议的接口。 AppKit将其用于授权。

您编写的子类可以实现这些方法。这与正式协议之间的区别在于使用@protocol ... @end表示法声明了正式协议。没有检查类是否实现给定的非正式协议。

我几乎总是使用正式协议,但我想如果你想提供默认行为,那么非正式协议很有用(只为你的类别提供可以覆盖的实现)。

答案 5 :(得分:3)

根据“Jonathan Sterling”的回答,我可以说以下代码代表非正式协议吗?

Apple文档:

“当用于声明协议时,类别接口没有相应的实现。相反,实现该协议的类在它们自己的接口文件中再次声明这些方法,并将它们与其实现文件中的其他方法一起定义。 “

#import <Foundation/Foundation.h>

@interface Cat1 : NSObject {


}
- (void) simpleMethod;

@end

@implementation Cat1

- (void) simpleMethod
{

    NSLog(@"Simple Method");
}

@end


@interface Cat1 (Cat2) 
- (void) addingMoreMethods;

@end




@interface MYClass : Cat1

@end

@implementation MYClass

- (void) addingMoreMethods
{
    NSLog(@"Testing!");
}
@end

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


    MYClass *myclass = [[MYClass alloc] init];
    [myclass addingMoreMethods];
    [myclass release];
    [pool drain];
    return 0;
}

答案 6 :(得分:1)

非正式协议定义了对象必须理解的方法。这称为“符合协议”。符合协议与类层次结构无关。 声明指针以保存对象的引用时,您可以定义此对象应符合的协议。如果您编写的代码分配的对象不符合所有必需的协议,那么您将在编译时收到警告。 非正式协议可帮助您依赖对象理解的一组方法。您不必在代码中调用isKindOfClass:或respondsTo:来检查传入的对象是否适合您的处理。 协议是一种面向方面的编程。