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还是原来的实例,不会变成父类对象。
三、重写父类方法时怎么维护委托对象
这里分两种场景:
- 父类的委托逻辑不需要子类干预:就像你的情况,用上面的“内部代理+私有方法”方案,把父类的委托逻辑封装在自己的私有实现里,子类碰不到,自然不会干扰。
- 委托逻辑允许子类定制:父类可以暴露一个委托属性,默认赋值为
self,子类可以选择重写这个属性或者替换委托对象:
这样Son如果想自己当委托,直接设置// 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]; } @endson.sessionDelegate = son;就行,不想的话就用默认的Dad逻辑。
另外要注意:重写父类方法时,如果需要保留父类的委托逻辑,一定要调用[super 方法名],不要把父类的实现完全覆盖掉,除非你明确要替换所有逻辑。
内容的提问来源于stack exchange,提问作者BigHeadCreations
相关产品推荐
相关产品推荐

