You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Objective-C中继承实现方法及重写父类方法时委托对象维护

嘿,我来帮你搞定这个问题,分三块说清楚:先解决你当前的session委托指向问题,再聊聊Objective-C里继承的核心逻辑,最后说重写父类方法时怎么维护委托对象。

一、解决Dad的session委托指向问题

你遇到的核心问题是:OC里不管调用父类还是子类的方法,self始终指向当前的实例(也就是你的Son对象),所以在Dad的setupSession里用delegate:self,自然就把Son设成了session的委托。要让Dad自己的session用Dad的逻辑处理委托回调,有个靠谱的方案——给Dad加一个专属的内部代理对象:

// Dad.m 文件里的实现
@interface Dad ()
// 私有方法,专门处理session的委托逻辑,子类无法直接重写(规范上不会去碰)
- (void)_handleSessionAuthChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler;
@end

// 内部代理类,专门帮Dad转发session委托回调
@interface DadInternalSessionDelegate : NSObject <NSURLSessionDelegate>
@property (nonatomic, weak) Dad *dad;
@end

@implementation DadInternalSessionDelegate
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler {
    // 直接调用Dad的私有处理方法
    [self.dad _handleSessionAuthChallenge:challenge completionHandler:completionHandler];
}
@end

@implementation Dad {
    NSURLSession *_dadSession;
    DadInternalSessionDelegate *_internalDelegate;
}

- (instancetype)init {
    self = [super init];
    if (self) {
        // 初始化内部代理,绑定当前Dad实例
        _internalDelegate = [[DadInternalSessionDelegate alloc] init];
        _internalDelegate.dad = self;
    }
    return self;
}

- (void)setupSession {
    NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
    // 用内部代理当session的委托,而不是self
    _dadSession = [NSURLSession sessionWithConfiguration:config delegate:_internalDelegate delegateQueue:[NSOperationQueue mainQueue]];
}

- (void)_handleSessionAuthChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler {
    // 这里写Dad自己的委托处理逻辑,完全不受子类影响
    completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil);
}
@end

这样一来,不管Son怎么调用[super setupSession],Dad的session都会用内部代理把回调转发到Dad的私有方法里,完全和Son的逻辑隔离开,达到你要的“Dad作为自身session委托”的效果。

二、Objective-C里的继承到底是怎么回事

OC是单继承语言,核心规则有这几条:

  • 子类会继承父类所有的实例变量(包括.m里的私有变量,只是子类无法直接访问)和方法(实例/类方法)。
  • 调用方法时,优先找子类的实现,如果子类没重写,才会走到父类的实现。
  • 不管在父类还是子类的方法里,self永远指向当前调用方法的那个实例(比如你调用[son startDadSession],所有方法里的self都是这个Son对象)。
  • super关键字的作用是强制调用父类的方法实现,但方法里的self还是原来的实例,不会变成父类对象。

三、重写父类方法时怎么维护委托对象

这里分两种场景:

  1. 父类的委托逻辑不需要子类干预:就像你的情况,用上面的“内部代理+私有方法”方案,把父类的委托逻辑封装在自己的私有实现里,子类碰不到,自然不会干扰。
  2. 委托逻辑允许子类定制:父类可以暴露一个委托属性,默认赋值为self,子类可以选择重写这个属性或者替换委托对象:
    // Dad.h
    @interface Dad : NSObject
    @property (nonatomic, weak) id<NSURLSessionDelegate> sessionDelegate;
    @end
    
    // Dad.m
    @implementation Dad
    - (instancetype)init {
        self = [super init];
        if (self) {
            _sessionDelegate = self; // 默认自己当委托
        }
        return self;
    }
    
    - (void)setupSession {
        _dadSession = [NSURLSession sessionWithConfiguration:config delegate:self.sessionDelegate delegateQueue:mainQueue];
    }
    @end
    
    这样Son如果想自己当委托,直接设置son.sessionDelegate = son;就行,不想的话就用默认的Dad逻辑。

另外要注意:重写父类方法时,如果需要保留父类的委托逻辑,一定要调用[super 方法名],不要把父类的实现完全覆盖掉,除非你明确要替换所有逻辑。

内容的提问来源于stack exchange,提问作者BigHeadCreations

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:41:44