消息转发机制在OC中模拟多继承以及实际使用场景

3 阅读4分钟

通过消息转发机制让OC模拟多继承是一种强大的技术手段。以下是完整的实现方案:

一、基础消息转发实现多继承

1. 快速转发方案(forwardingTargetForSelector:

// 多继承模拟类
@interface MultiInheritObject : NSObject
@property (nonatomic, strong) NSMutableDictionary *forwardingTargets;
@end

@implementation MultiInheritObject

- (instancetype)init {
    self = [super init];
    if (self) {
        _forwardingTargets = [NSMutableDictionary dictionary];
    }
    return self;
}

// 添加转发目标
- (void)addForwardingTarget:(id)target forProtocol:(Protocol *)protocol {
    NSString *protocolName = NSStringFromProtocol(protocol);
    self.forwardingTargets[protocolName] = target;
}

// 核心转发方法
- (id)forwardingTargetForSelector:(SEL)aSelector {
    // 遍历所有转发目标,找到能响应此方法的对象
    for (id target in self.forwardingTargets.allValues) {
        if ([target respondsToSelector:aSelector]) {
            return target;
        }
    }
    return [super forwardingTargetForSelector:aSelector];
}

@end

2. 完整使用示例

// 定义两个"父类"
@interface Animal : NSObject
- (void)eat;
- (void)sleep;
@end

@implementation Animal
- (void)eat { NSLog(@"Animal eating"); }
- (void)sleep { NSLog(@"Animal sleeping"); }
@end

@interface Machine : NSObject
- (void)work;
- (void)repair;
@end

@implementation Machine
- (void)work { NSLog(@"Machine working"); }
- (void)repair { NSLog(@"Machine repairing"); }
@end

// 使用多继承模拟
MultiInheritObject *multiObj = [[MultiInheritObject alloc] init];
Animal *animal = [[Animal alloc] init];
Machine *machine = [[Machine alloc] init];

[multiObj addForwardingTarget:animal forProtocol:@protocol(NSObject)];
[multiObj addForwardingTarget:machine forProtocol:@protocol(NSObject)];

// 现在multiObj可以调用两个"父类"的方法
[multiObj eat];    // 输出: Animal eating
[multiObj work];   // 输出: Machine working

OC消息转发实现多继承

核心实现方案

1. 快速转发方案

- (id)forwardingTargetForSelector:(SEL)aSelector {
    for (id target in self.forwardingTargets) {
        if ([target respondsToSelector:aSelector]) {
            return target;
        }
    }
    return [super forwardingTargetForSelector:aSelector];
}

2. 完整消息转发方案

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
    for (id parent in self.parentObjects) {
        if ([parent respondsToSelector:aSelector]) {
            return [parent methodSignatureForSelector:aSelector];
        }
    }
    return [super methodSignatureForSelector:aSelector];
}

- (void)forwardInvocation:(NSInvocation *)anInvocation {
    for (id parent in self.parentObjects) {
        if ([parent respondsToSelector:anInvocation.selector]) {
            [anInvocation invokeWithTarget:parent];
            return;
        }
    }
    [super forwardInvocation:anInvocation];
}

实际应用场景

1. 模块解耦

// 服务定位器模式
- (id)forwardingTargetForSelector:(SEL)aSelector {
    for (id service in self.services.allValues) {
        if ([service respondsToSelector:aSelector]) {
            return service;
        }
    }
    return [super forwardingTargetForSelector:aSelector];
}

2. 容错处理

// 安全的Delegate包装器
- (id)forwardingTargetForSelector:(SEL)aSelector {
    if ([self.originalDelegate respondsToSelector:aSelector]) {
        return self.originalDelegate;
    }
    return nil; // 防止崩溃
}

3. AOP编程

// 性能监控
- (id)forwardingTargetForSelector:(SEL)aSelector {
    CFTimeInterval start = CACurrentMediaTime();
    id result = [self.originalTarget forwardingTargetForSelector:aSelector];
    CFTimeInterval duration = (CACurrentMediaTime() - start) * 1000;
    NSLog(@"%@ 执行时间: %.2fms", NSStringFromSelector(aSelector), duration);
    return result;
}

Swift多继承替代方案

1. 协议 + 协议扩展

protocol Flyable { func fly() }
protocol Swimmable { func swim() }

extension Flyable { func fly() { print("默认飞行") } }
extension Swimmable { func swim() { print("默认游泳") } }

class SuperAnimal: Flyable, Swimmable { 
    // 自动获得默认实现
}

2. 协议组合

typealias Amphibious = Flyable & Swimmable
func handleAmphibious(_ creature: Amphibious) {
    creature.fly()
    creature.swim()
}

OC与Swift协议对比

OC协议局限:

  • 无默认实现:必须实现所有协议方法
  • 无关联类型:无法表达泛型概念
  • 编译时限制:缺少协议扩展能力

Swift协议优势:

  • 协议扩展:提供默认实现
  • 关联类型:支持泛型协议
  • 类型安全:编译时检查

在 Swift 中,泛型协议主要通过以下两种方式实现:

1. 关联类型协议 - 主要的泛型协议

这是 Swift 中最接近"泛型协议"的概念,使用 associatedtype 关键字:

// 定义泛型协议
protocol Container {
    associatedtype Item
    var count: Int { get }
    mutating func append(_ item: Item)
    subscript(i: Int) -> Item { get }
}

// 实现协议时指定具体类型
struct IntStack: Container {
    typealias Item = Int  // 明确指定关联类型
    private var items: [Item] = []
    
    var count: Int { items.count }
    
    mutating func append(_ item: Item) {
        items.append(item)
    }
    
    subscript(i: Int) -> Item {
        return items[i]
    }
}

// 或者让编译器自动推断
struct GenericStack<Element>: Container {
    // 编译器自动推断 Item = Element
    private var items: [Element] = []
    
    var count: Int { items.count }
    
    mutating func append(_ item: Element) {
        items.append(item)
    }
    
    subscript(i: Int) -> Element {
        return items[i]
    }
}

2. 带 Self 要求的协议

使用 Self 关键字来引用实现类型:

protocol Equatable {
    static func == (lhs: Self, rhs: Self) -> Bool
}

protocol Comparable: Equatable {
    static func < (lhs: Self, rhs: Self) -> Bool
    static func <= (lhs: Self, rhs: Self) -> Bool
    static func >= (lhs: Self, rhs: Self) -> Bool
    static func > (lhs: Self, rhs: Self) -> Bool
}

// 实现
struct Person: Comparable {
    let name: String
    let age: Int
    
    static func == (lhs: Person, rhs: Person) -> Bool {
        return lhs.name == rhs.name && lhs.age == rhs.age
    }
    
    static func < (lhs: Person, rhs: Person) -> Bool {
        return lhs.age < rhs.age
    }
}

高级用法

关联类型约束

protocol SuffixableContainer: Container {
    associatedtype Suffix: SuffixableContainer where Suffix.Item == Item
    func suffix(_ size: Int) -> Suffix
}

// 实现
struct Stack<Element>: SuffixableContainer {
    private var items: [Element] = []
    
    // Container 要求
    var count: Int { items.count }
    
    mutating func append(_ item: Element) {
        items.append(item)
    }
    
    subscript(i: Int) -> Element {
        return items[i]
    }
    
    // SuffixableContainer 要求
    func suffix(_ size: Int) -> Stack {
        let result = Stack()
        result.items = Array(items.suffix(size))
        return result
    }
}

协议组合与泛型

protocol Identifiable {
    associatedtype ID: Hashable
    var id: ID { get }
}

protocol Named {
    var name: String { get }
}

// 使用泛型约束
func processItems<T: Identifiable & Named>(_ items: [T]) where T.ID == Int {
    for item in items {
        print("Item \(item.id): \(item.name)")
    }
}

// 或者使用 some 关键字 (Swift 5.7+)
func getItem() -> some Identifiable & Named {
    return SomeConcreteType()
}

使用场景对比

特性关联类型协议Self 要求协议
适用场景容器、集合、数据源比较、序列化、拷贝
灵活性高,可适配多种类型中等,限于自身类型
复杂度较高相对简单

实际应用示例

// 网络请求泛型协议
protocol APIRequest {
    associatedtype Response: Decodable
    var endpoint: String { get }
    var method: HTTPMethod { get }
    func decode(_ data: Data) throws -> Response
}

// 具体实现
struct UserRequest: APIRequest {
    typealias Response = User
    
    let endpoint = "/users"
    let method: HTTPMethod = .get
    
    func decode(_ data: Data) throws -> User {
        return try JSONDecoder().decode(User.self, from: data)
    }
}

// 使用泛型网络客户端
class APIClient {
    func send<T: APIRequest>(_ request: T) async throws -> T.Response {
        // 网络请求实现...
        let data = Data()
        return try request.decode(data)
    }
}

重要限制

Swift 的泛型协议(关联类型协议)不能直接用作类型

// ❌ 错误:不能直接使用
let container: Container = SomeContainer()

// ✅ 正确:使用泛型约束
func processContainer<C: Container>(_ container: C) where C.Item == Int {
    // 处理容器
}

总结:Swift 中的"泛型协议"主要是通过 关联类型 实现的,它提供了强大的类型抽象能力,但在使用时需要注意类型擦除等高级技巧。

要点

  1. OC多继承:通过消息转发机制模拟,有性能开销
  2. Swift多继承:通过协议+协议扩展实现,类型安全
  3. 实际应用:模块解耦、容错处理、AOP编程
  4. 选择建议:OC用于运行时灵活,Swift用于类型安全

核心区别:OC是"接口多继承",Swift是"实现多继承"