面试题答案
一键面试@protocol的高级特性
协议的继承
- 概念:一个协议可以继承自另一个或多个协议。当一个协议继承其他协议时,它会获得被继承协议中定义的所有方法声明。例如:
@protocol BaseProtocol <NSObject>
- (void)baseMethod;
@end
@protocol SubProtocol <BaseProtocol>
- (void)subMethod;
@end
这里SubProtocol
继承自BaseProtocol
,遵守SubProtocol
的类需要实现baseMethod
和subMethod
。
- 作用:通过协议继承,可以创建协议的层次结构,复用通用的方法声明,减少代码冗余。例如在一个图形绘制框架中,可以有一个
ShapeProtocol
定义基本的绘制方法,然后CircleProtocol
和RectangleProtocol
继承自ShapeProtocol
并添加各自特有的方法。
可选方法
- 概念:在协议定义中,可以使用
@optional
关键字标记一些方法为可选的。遵守该协议的类不必实现这些可选方法。例如:
@protocol DataSourceProtocol <NSObject>
- (NSInteger)numberOfItems;
@optional
- (NSString *)titleForItemAtIndex:(NSInteger)index;
@end
- 作用:在实际项目中,很多情况下某些功能不是所有遵守协议的类都必须实现的。比如在一个表格视图数据源协议中,
numberOfItems
方法是必须实现的,以告知表格有多少行数据,而titleForItemAtIndex:
方法可能是可选的,用于设置每行的标题,如果不需要设置标题,遵守协议的类可以不实现该方法。
协议的合成
- 概念:一个协议可以由多个其他协议合成。通过在尖括号中列出多个协议,用逗号分隔。例如:
@protocol NewProtocol <Protocol1, Protocol2, Protocol3>
// 可以定义自己特有的方法
@end
- 作用:在构建复杂的软件架构时,将多个相关的协议合成一个新协议,可以让遵守该新协议的类同时拥有多个协议的功能。比如在一个多媒体应用中,可以将
PlayableProtocol
(定义播放相关方法)、RecordableProtocol
(定义录制相关方法)合成一个MultimediaDeviceProtocol
,供设备类遵守。
构建灵活、可维护的软件架构
- 利用协议继承:在分层架构中,上层协议可以继承下层协议的基本功能,实现功能的逐步扩展。例如在网络请求模块中,有一个基础的
NetworkRequestProtocol
定义了通用的请求方法,APINetworkRequestProtocol
继承自它并添加了与特定API相关的请求方法。这样不同的网络请求类可以根据需求遵守不同层次的协议,使得架构更加清晰,易于维护和扩展。 - 利用可选方法:在视图控制器与数据源对象的交互中,使用可选方法可以避免数据源对象必须实现一些不必要的方法。例如在一个自定义视图中,视图控制器可能需要从数据源获取一些数据并显示,有些数据获取方法可能是可选的,根据实际业务需求,数据源对象可以选择实现或不实现这些方法,提高了代码的灵活性。
- 利用协议的合成:在一个综合的业务模块中,将多个功能相关的协议合成一个协议,可以让模块之间的交互更加简洁。例如在一个电商应用中,商品展示模块可能需要同时具备可点击、可收藏、可分享等功能,将
ClickableProtocol
、FavoriteProtocol
、ShareableProtocol
合成一个ProductInteractionProtocol
,商品展示类遵守该协议后就同时拥有了这些功能。
多协议实现时可能遇到的问题及解决方案
方法冲突
- 问题:当一个类遵守多个协议,而这些协议中定义了相同方法签名的方法时,会出现方法冲突。例如,
ProtocolA
和ProtocolB
都定义了- (void)doSomething;
方法,一个类同时遵守这两个协议,在实现该方法时就会产生困惑,不知道该方法具体是为哪个协议实现的。 - 解决方案:可以通过文档注释清晰地说明该方法是为哪个协议实现的,并且尽量避免在不同协议中定义相同签名的方法。如果无法避免,可以在协议设计时尽量将这些方法定义在一个公共的父协议中,通过协议继承来复用。
冗余实现
- 问题:如果多个协议中有一些相似或重复的方法声明,遵守这些协议的类可能需要重复实现这些方法,造成代码冗余。
- 解决方案:使用协议继承,将这些重复的方法提取到一个公共的父协议中,让其他协议继承该父协议。或者通过创建一个基类,在基类中实现这些重复方法,让遵守多个协议的类继承自该基类,避免重复实现。
协议层次复杂
- 问题:随着项目的发展,协议的继承和合成可能会导致协议层次变得复杂,难以理解和维护。
- 解决方案:在设计协议时,要保持清晰的层次结构和良好的命名规范。定期对协议进行整理和重构,去除不必要的继承和合成关系。同时,通过详细的文档说明每个协议的作用和层次关系,方便其他开发人员理解和维护。