面试题答案
一键面试运行时情况
在运行时,当调用该同名实例方法时,会调用类别(category)中定义的方法,原类中的同名方法被“覆盖”。这是因为在Objective - C的运行时系统中,消息传递机制会根据对象的类方法列表来查找并执行方法。类别在运行时会被动态添加到类的方法列表中,而且在查找方法时,类别中的方法会优先于原类中的同名方法被找到并执行。
内存管理注意事项
- 内存泄漏风险:如果类别方法中对对象的属性进行了内存分配操作,但没有正确地进行释放,就可能导致内存泄漏。例如,在类别方法中使用
alloc
创建了一个新的对象,但在方法结束时没有调用release
或使用自动释放池,随着方法的多次调用,内存会不断被占用而无法释放。 - 属性合成与内存管理:如果类别中通过
@synthesize
合成属性,需要注意其内存管理语义。比如对于retain
或strong
类型的属性,要确保在适当的时候进行内存释放,避免过度保留导致对象无法释放;对于assign
类型的属性,要避免指向已释放的对象,产生野指针问题。
消息传递机制注意事项
- 方法签名不匹配:虽然类别可以覆盖原类的同名方法,但如果类别中方法的实现与原类方法的预期签名不一致,可能会导致未定义行为。例如,原类方法期望接收特定数量和类型的参数,而类别方法的参数列表不同,在消息传递时,运行时系统按照原类方法的签名去传递参数,就可能导致程序崩溃或出现逻辑错误。
- 继承关系中的影响:如果子类继承自包含被类别覆盖方法的父类,子类调用该方法时会执行类别中的版本。但如果子类自己也重写了该方法,那么子类的方法会优先于类别方法执行。在复杂的继承体系中,需要清晰地理解这种方法查找优先级,以避免出现意外的行为。
- 多个类别同名方法:如果一个类有多个类别都定义了同名方法,那么最终调用哪个类别中的方法取决于编译和链接顺序。这种不确定性在开发中需要特别注意,尽量避免在不同类别中定义同名方法,以免出现难以调试的问题。