MST
星途 面试题库

面试题:Swift与Objective-C混编中的复杂类继承与方法调用

假设你有一个Objective - C的基类`BaseObjCClass`,它有一个虚方法`performAction`。现在有一个Swift子类`SubSwiftClass`继承自`BaseObjCClass`,并在Swift子类中重写`performAction`方法。当通过一个`BaseObjCClass`类型的指针调用`performAction`方法时,如何确保调用到正确的Swift子类实现?在不同的编译选项和运行环境下,这种机制会有什么变化?请详细说明并给出代码示例。
20.2万 热度难度
编程语言Swift

知识考点

AI 面试

面试题答案

一键面试
  1. 确保调用到正确的Swift子类实现
    • 在Objective - C中,虚方法(Objective - C中没有严格意义的虚方法概念,这里类比C++虚函数的概念,实际是动态方法调度)是通过动态方法调度机制来实现的。当在Swift子类SubSwiftClass中重写BaseObjCClassperformAction方法时,只要遵循Objective - C的动态方法调度规则,就可以确保通过BaseObjCClass类型的指针调用performAction方法时,会调用到SubSwiftClass中重写的实现。
    • 为了在Swift中与Objective - C进行交互,需要在Swift类定义前添加@objc修饰符,这样Swift类才能在Objective - C运行时可见,并且其重写的方法也能被正确调度。
  2. 不同编译选项和运行环境下的机制变化
    • 编译选项
      • 通常情况下,只要Swift类标记了@objc,并且方法签名在Objective - C和Swift之间能够正确映射,动态方法调度就会正常工作。如果在编译时开启了优化选项,编译器可能会对方法调用进行内联等优化,但这一般不会影响动态方法调度的正确性。例如,在Xcode中,可以通过设置Optimization Level编译选项来调整优化程度。
    • 运行环境
      • 在不同的iOS或macOS版本中,Objective - C运行时的底层实现基本保持一致,所以动态方法调度机制不会有太大变化。但是,在一些特殊情况下,如应用程序在不同架构(如ARM64、x86_64)的设备上运行时,由于指令集等差异,方法调用的底层实现细节可能略有不同,但整体的动态方法调度逻辑是不变的。
  3. 代码示例
    • Objective - C基类代码(BaseObjCClass.h)
#import <Foundation/Foundation.h>

@interface BaseObjCClass : NSObject

- (void)performAction;

@end
  • Objective - C基类代码(BaseObjCClass.m)
#import "BaseObjCClass.h"

@implementation BaseObjCClass

- (void)performAction {
    NSLog(@"BaseObjCClass performAction");
}

@end
  • Swift子类代码(SubSwiftClass.swift)
import Foundation

@objc class SubSwiftClass: BaseObjCClass {
    override func performAction() {
        print("SubSwiftClass performAction")
    }
}
  • 测试代码(在Objective - C中测试,假设在main.m文件中)
#import <Foundation/Foundation.h>
#import "BaseObjCClass.h"
// 引入Swift生成的头文件,假设项目名为MyProject
#import "MyProject - Swift.h" 

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        BaseObjCClass *baseObj = [[SubSwiftClass alloc] init];
        [baseObj performAction];
    }
    return 0;
}

在上述代码中,SubSwiftClass标记了@objc,重写了performAction方法。通过BaseObjCClass类型的指针baseObj指向SubSwiftClass的实例,并调用performAction方法,会调用到SubSwiftClass中重写的实现。