面试题答案
一键面试对耦合度的影响
- 降低耦合度:
- 当协议中存在
@optional
方法时,遵循该协议的类不必强制实现这些方法。这使得类与协议之间的耦合度降低。例如,一个视图控制器协议可能定义了一些可选的方法用于处理复杂的视图更新逻辑,部分简单的视图控制器不需要这些复杂逻辑,就可以不实现这些@optional
方法,仅关注自己需要的功能,从而减少了对协议中不必要功能的依赖。
- 当协议中存在
- 可能增加潜在耦合:
- 然而,如果在协议使用者中过度依赖
@optional
方法的存在,并且在运行时频繁检查方法是否实现,会增加代码之间的潜在耦合。比如,一个对象在调用协议的@optional
方法前,通过respondsToSelector:
等方式检查,若其他遵循协议的类未按预期实现该方法,可能导致运行时错误,此时调用者和实现者之间存在了一种隐式的耦合关系。
- 然而,如果在协议使用者中过度依赖
对可维护性的影响
- 增加灵活性,利于维护:
@optional
方法为遵循协议的类提供了更多的灵活性。在软件维护过程中,如果需要对协议进行修改或扩展,添加新的功能,通过将新方法定义为@optional
,可以避免强制所有遵循该协议的类立即实现新功能,从而减少了对现有代码的大规模改动,降低了维护成本。例如,一个社交应用的用户资料展示协议,若要新增一个获取用户兴趣爱好的功能,将获取兴趣爱好的方法定义为@optional
,旧版本的用户资料展示类可以继续正常工作,而新的展示类可根据需求选择是否实现该方法。
- 可能导致代码混乱:
- 另一方面,如果
@optional
方法过多,或者使用不规范,可能会使协议的意图变得不清晰,给维护人员带来困扰。例如,协议中部分@optional
方法虽然可选,但对于某些特定场景却是必需的,如果没有清晰的文档说明,维护人员很难快速理解每个@optional
方法的使用场景和必要性,从而增加了维护难度。
- 另一方面,如果
对扩展性的影响
- 促进扩展性:
@optional
方法为协议的扩展提供了便利。随着软件需求的增长,当需要在协议中添加新的功能时,可以将新方法定义为@optional
,这样既不会破坏现有的遵循该协议的类的实现,又为未来的类提供了扩展的可能性。例如,一个支付协议,最初只有基本的支付功能,后续若要添加支付结果通知回调等功能,将新的回调方法定义为@optional
,使得旧的支付类无需修改,新的支付类可按需实现这些新功能,方便协议的功能扩展。
- 需谨慎使用:
- 但如果扩展性设计不合理,例如随意添加
@optional
方法,可能导致协议变得臃肿。过多的@optional
方法可能使遵循协议的类难以抉择哪些方法真正对自己有用,也可能使协议的核心功能被淹没在众多可选功能中,不利于协议的长期扩展和演进。
- 但如果扩展性设计不合理,例如随意添加
合理使用 @optional
方法的建议
- 明确设计意图:
- 在设计协议时,首先要明确哪些功能是核心的、必须实现的,哪些是可选的扩展功能。对于核心功能,应定义为
@required
(默认情况下协议方法为@required
),确保遵循协议的类提供基本的功能实现。对于一些特定场景下才需要的功能,或者对现有类兼容性要求较高的新功能,可定义为@optional
。
- 在设计协议时,首先要明确哪些功能是核心的、必须实现的,哪些是可选的扩展功能。对于核心功能,应定义为
- 清晰的文档说明:
- 对每个
@optional
方法都要提供详细的文档说明,包括方法的作用、何时需要实现、调用时机、参数含义以及返回值意义等。这样可以帮助其他开发人员在遵循协议时,快速理解每个@optional
方法的用途,避免误解和错误使用。
- 对每个
- 避免过度使用:
- 尽量控制
@optional
方法的数量,避免协议变得过于复杂和臃肿。如果发现协议中有大量的@optional
方法,可能需要重新审视协议的设计,考虑是否可以将其拆分为多个更细粒度的协议,或者对部分可选功能进行整合和优化。
- 尽量控制
- 考虑运行时检查的合理性:
- 在调用
@optional
方法时,要谨慎进行运行时检查。如果频繁检查方法是否实现,可能意味着设计上存在问题。尽量通过合理的协议设计,使得调用者无需过多关心方法是否可选,减少运行时的不确定性。同时,要确保在检查方法实现后进行的操作是安全的,避免因方法未实现而导致的运行时错误。
- 在调用