继承和协议

从 C++ 到 Objective-C(7):继承

简单继承

Objective-C 也有继承的概念,但是不能多重继承。不过,它也有别的途径实现类似多重继承的机制,这个我们后面会讲到。

C++

Objective-C

class Foo : public Bar,

            protected Wiz

{

}

@interface Foo : Bar // 单继承

// 如果要同时“继承” Wiz,需要使用另外的技术

{

}

@end

在 C++ 中,一个类可以继承自一个或多个类,使用 public、protected 以及 private 修饰符。子类的函数如果要调用父类的版本,需要使用 :: 运算符,例如 Bar::,Wiz:: 等。

在 Objective-C 中,一个类只能继承一个父类,并且只能是 public 的(这和 Java 是一致的)。同样类似 Java,如果你要在子类中调用父类的函数,需要使用 super。

多重继承

Java 同样不允许多重继承。但是它提供了 interface 来模拟多重继承。类似的,Objective-C 也有同样的机制,这就是协议 protocol和分类 categories。我们将在后面的内容详细讲述这两种技术。

虚拟性

虚方法

在 Objective-C 中,所有方法都是虚的,因此,没有 virtual 关键字或其等价物。

虚方法重定义

在 Objective-C 中,你可以定义一个没有在 @interface 块里面声明的方法。但这并不是一种替代 private 的机制,因为这种方法实际是能够被调用的(回想下,Objective-C 中方法的调用是在运行期决定的)。不过,这确实能够把接口定义变得稍微干净了一些。

这并不是一种坏习惯,因为有时你不得不重定义父类的函数。由于所有方法都是虚的,你无需像 C++ 一样在声明中显式写明哪些函数是 virtual 的,这种做法就成为一种隐式的重定义。很多继承西 NSObject 的方法都是是用这种方法重定义的。例如构造方法 init,析构方法 dealloc,view 类的 drawRect: 等等。这样的话,接口就变得更简洁,更易于阅读。不好之处就是,你不能知道究竟哪些方法被重定义了。

纯虚方法则是使用正式协议 formal protocols 来实现。

虚继承

Objective-C 中不允许多重继承,因此也就没有虚继承的问题。

协议

Java 和 C# 使用接口 interface 的概念来弥补多重继承的不足。Objective-C 也使用了类似的机制,成为协议 protocol。在 C++ 中,这种概念是使用抽象类。协议并不是真正的类:它只能声明方法,不能添加数据。有两种类型的协议:正式的 formal 和非正式的 informal。

正式协议

正式协议的方法,所有实现这个协议的类都必须实现。这就是一种验证,也就是说,只要这个类说实现这个协议,那么它肯定可以处理协议中规定的方法。一个类可以实现任意多个协议。

C++

class MouseListener

{

public:

    virtual bool mousePressed(void) = 0; // 纯虚方法

    virtual bool mouseClicked(void) = 0; // 纯虚方法

};

 

class KeyboardListener

{

public:

    virtual bool keyPressed(void) = 0; // 纯虚方法

};

 

class Foo : public MouseListener,  public KeyboardListener {...}

// Foo 必须实现 mousePressed, mouseClicked 和 keyPressed

// 然后 Foo 就可以作为鼠标和键盘的事件监听器

Objective-C

@protocol MouseListener

 

-(BOOL) mousePressed;

-(BOOL) mouseClicked;

 

@end

 

@protocol KeyboardListener

 

-(BOOL) keyPressed;

 

@end

 

@interface Foo : NSObject <MouseListener, KeyboardListener>

{

...

}

@end

// Foo 必须实现 mousePressed, mouseClicked 和 keyPressed

// 然后 Foo 就可以作为鼠标和键盘的事件监听器

C++ 中,协议可以由抽象类和纯虚函数实现。C++ 的抽象类要比 Objective-C 的协议强大的多,因为抽象类可以带有数据。

Objective-C 中,协议是一个特殊的概念,使用尖括号 <…> 表明。注意,尖括号在 Objective-C 中不是模板的意思,Objective-C 中没有类似 C++ 模板的概念。

一个类也可以不经过协议声明,直接实现协议规定的方法。此时,conformsToProtocol: 方法依然返回 NO。出于性能考虑,conformsToProtocol: 方法只检查类接口的声明,不会一个方法一个方法的对比着检查。conformsToProtocol: 的返回值并不会作为是否调用方法的依据。下面是这个方法的原型:

-(BOOL) conformsToProtocol:(Protocol*)protocol

// Protocol 对象可以由 @protocol(协议名) 返回

实现了正式协议的对象的类型同协议本身是兼容的。这一机制可以作为协议的筛选操作。例如:

// 下面方法是 Cocoa 提供的标准方法

// 方法参数可以是任意类型 id,但是必须兼容 NSDraggingInfo 协议

-(NSDragOperation) draggingEntered:(id )sender;

可选方法

有时我们需要这么一种机制:我们的类需要实现一部分协议中规定的方法,而不是整个协议。例如在 Cocoa 中,代理的概念被广泛使用:一个类可以给定一个辅助类,由这个辅助类去完成部分任务。

一种实现是将一个协议分割成很多小的协议,然后这个类去实现一个协议的集合。不过这并不具有可操作性。更好的解决方案是使用非正式协议。在 Objective-C 1.0 中就有非正式协议了,Objective-C 2.0 则提出了新的关键字 @optional 和 @required,用以区分可选方法和必须方法。

@protocol Slave

 

@required // 必须部分

-(void) makeCoffee;

-(void) duplicateDocument:(Document*)document count:(int)count;

 

@optional // 可选部分

-(void) sweep;

 

@required // 又是一个必须部分

-(void) bringCoffee;

@end

非正式协议

非正式协议并不是真正的协议,它对代码没有约束力。非正式协议允许开发者将一些方法进行归类,从而可以更好的组织代码。所以,非正式协议并不是协议的宽松版本。另外一个相似的概念就是分类。

让我们想象一个文档管理的服务。假设有绿色、蓝色和红色三种文档,一个类只能处理蓝色文档,而 Slave 类使用三个协议 manageBlueDocuments, manageGreenDocuments 和 manageRedDocuments。Slave 可以加入一个分类 DocumentsManaging,用来声明它能够完成的任务。分类名在小括号中被指定:

@interface Slave (DocumentsManaging)

 

-(void) manageBlueDocuments:(BlueDocument*)document;

-(void) trashBlueDocuments:(BlueDocument*)document;

 

@end

任何类都可以加入 DocumentsManaging 分类,加入相关的处理方法:

@interface PremiumSlave (DocumentsManaging)

 

-(void) manageBlueDocuments:(BlueDocument*)document;

-(void) manageRedDocuments:(RedDocument*)document;

 

@end

另一个开发者就可以浏览源代码,找到了 DocumentsManaging 分类。如果他觉得这个分类中有些方法可能对自己,就会检查究竟哪些能够使用。即便他不查看源代码,也可以在运行时指定:

if([mySlave respondsToSelector:@selector(manageBlueDocuments:)])

    [mySlave  manageBlueDocuments:document];

严格说来,除了原型部分,非正式协议对编译器没有什么意义,因为它并不能约束代码。不过,非正式协议可以形成很好的自解释性代码,让 API 更具可读性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值