Objective C 协议(Protocol)

本文深入讲解Objective-C中的协议概念,包括正式协议与非正式协议的区别、如何声明与采纳协议、使用NSCopying协议进行对象复制等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

协议

          Objective-C的另一个扩展称为协议,它非常象Java中的接口。两者都是通过一个简单的方法声明列表发布一个接口,任何类都可以选择实现。协议中的方法通过其它类实例发送的消息来进行调用。

         协议的主要价值和类别一样,在于它可以作为子类化的又一个选择。它们带来了C++多重继承的一些优点,使接口(如果不是实现的话)可以得到共享。协议是一个类在声明接口的同时隐藏自身的一种方式。接口可以暴露一个类提供的所有(通常是这种情况)或部分服务。类层次中的其它类都可以通过实现协议中的方法来访问协议发布的服务,不一定和协议类有继承关系(甚至不一定具有相同的根类)。通过协议,一个类即使对另一个类的身份(也就是类的类型)一无所知,也可以和它进行由协议定义的特定目的的交流。

         有两种类型的协议:正式和非正式协议。

          ①非正式协议:非正式协议在"类别(Category)"部分中已经简单介绍了,它们是NSObject类中定义的类别。因此每个以NSObject为根类的对象(和类对象)都隐式采纳了类别中发布的接口。 与正式协议不同,一个类不必实现非正式协议中的每个方法,而是只实现它感兴趣的方法就可以了。为了使非正式协议正确工作,声明非正式协议的类在向某个目标对象发送协议消息之前,必须首先向它发送respondsToSelector:消息并得到肯定的回答(如果目标对象没有实现相应的方法,则产生一个运行时例外)在可选协议方法被引入Objective-C 2.0之前,非正式协议实质上是Foundation和AppKit 类用于实现委托的方式。

         ②正式协议:

正式协议声明一个方法列表,协议采纳者需要实现表中所有方法。正式协议有特殊的声明、采纳以及类型检查语法。您可以使用@required@optional关键字指定方法必须实现或可选实现。子类将会继承其祖先类所采用的正式协议。一个正式协议也可以采纳其他的协议。

正式协议是对Objective-C语言的扩展。Cocoa中的协议通常指的是正式协议。与非正式协议不同的是,正式协议要求显式地采用协议。它使一个类可以正式地声明一个方法列表,作为向外提供服务的接口。Objective-C语言和运行系统支持正式协议;编译器可以根据协议进行类型检查,对象可以在运行时进行检查,以确认是否遵循某个协议。正式协议有自己的专用术语和语法。术语方面,提供者和客户的意义有所不同:

  • 提供者(通常是一个类)声明正式的协议。
  • 客户类采纳正式协议,表示客户类同意实现协议中所有的方法。
  • 如果一个类采纳某协议或者是从采纳该协议的类派生出来的(协议可以被子类继承),则可以说该类遵循该协议。

一.正式协议(Protocol)

Objective-C中,声明和采纳协议都有自己的语法。协议的声明必须使用编译导向符@protocolObjective C 2.0之后加入新的语法特性@required和@optional

1.1声明协议

@protocol ProtocolName

//method declarations

@end

示例如下:

//NSCopying协议

@protocol NSCopying

- (id)copyWithZone:(NSZone*) zone;

@end

//NSCoding协议

@protocol NSCoding

- (void)encodeWithCoder:(NSCoder *)aCoder;

- (id)initWithCoder:(NSCoder *)aDecoder;

@end

1.2 类声明中采用协议

       如果一个类要采纳某个协议,需要在在@interface导向符后、紧接着超类的位置上指定协议的名称,并包含在尖括号中。一个类可以采纳多个协议,不同的协议之间用逗号分隔。 

@interface Car:NSObject<NSCopying>

{

//instance variables

}

//methods

@end//Car

//采用多个协议

@interface Car:NSObject<NSCopying,NSCoding,ProtocolName1,...>

{

//instance variables

}

//methods

@end//Car

1.3 Objective-C 2.0增加了两个新的协议修饰符:@optionnal和@required,默认是@required 

@protocol MyProtocol
- (void)requiredMethod;
@optional
- (void)anOptionalMethod;
- (void)anotherOptionalMethod;
@required
- (void)anotherRequiredMethod;
@end//MyProtocol

1.4 检查一个类是否遵循特定的协议(conformsToProtocol:)

         Objective-C通过类遵循的协议和类继承的超类来定义类的类型。您可以通过发送conformsToProtocol:消息来检查一个类是否遵循特定的协议:

if ([anObject conformsToProtocol:@protocol(MyProtocol)]){

    // do something appropriate

}

1.5 协议和数据类型

         你可以在使用的数据类型中为实例变量和方法参数指定协议名称。这样您就可以通过编译器来得到另一个级别的类型检查,这种检查比较抽象,因为它不和特定的实现相关联。您可以使用与协议采纳相同的语法规则,即把协议的名称放在尖括号中,通过这种语法可以在类型中指定遵循的协议。您常常会看到在这些声明中使用了动态对象类型id,例如:

    - (void)draggingEnded:(id <NSDraggingInfo>)sender;

        这里,参数中引用的对象可以是任意类型的类,但是必须遵循NSDraggingInfo协议。

        除了目前为止已经提到的协议之外,Cocoa还提供了几个协议的例子。一个有趣的例子就是NSObject协议。可以想象得到的是,NSObject类采纳了这个协议,还有一个根类NSProxy也采纳了这个协议。通过这个协议,NSProxy类可以和Objective-C运行环境的一部分进行交互,包括引用计数、内省、和对象行为的其它基础部分。

       正式协议有其自己的限制。如果协议声明的方法列表随着时间而增长,协议的采纳者就会不再遵循该协议。因此,Cocoa中的正式协议被用于稳定的方法集合,比如NSCopyingNSCoding。如果您预期协议方法会增多,则可以声明为非正式协议,而不是正式协议。

二. 使用NSCopying协议复制
    复制分为深层复制(Deep Copy)和浅层复制(Shallow Copy)
   浅层复制:NSArray类的copy方法是浅层复制,当复制一个NSArray类的对象时,你复制的对象只复制指向引用对象的指针,而不是复制引用对象本身。如果复制一个NSArray类的对象,该对象包含5个NSString类的对象,你最终得到的是5个可供程序使用的字符串对象,而不是10个字符串对象。
   深层复制:将复制所有的引用对象。

2.1 复制Engine
   @interface Engine : NSObject<NSCopying>
    @end//Engine

    - (id)copyWithZone:(NSZone*)zone
   {
         Engine *engineCopy;
         engineCopy = [[[self class] allocWithZone:zone] init];
         return engineCopy;
    }
2.2 复制Tire
   @interface Tire:NSObject<NSCopying>
   {
       float pressure;
       float treadDepth;
   }
   //methods
   @end//Tire
   - (id) copyWithZone:(NSZone*)zone
   {
       Tire *tireCopy;
       tireCopy = [[[self class] allocWithZone:zone] initWithPressure:pressure treadDepth:treadDepth];
       return tireCopy;
    }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值