How to find out whether to call a superclass method in Objective-C

The Child class extends the parent. Parent implements the C protocol, which has optional methods, including -(void)d . The child has an implementation -d ; if he calls [super d] ?

In other words, what code do I write to call [super d] if and only if something answers it? Suppose I do not control the implementation of Parent; he can change at any time.

That is all I was thinking. I am currently using number 4.

Obvious reasonable answer 1:

 [super d]; // Delete this line if a runtime exception occurs when you try it 

This does not work, because Parent can implement -d dynamically, so it works when you check it, and not in the field. Or the implementation of the parent may change, so the result of this test is no longer correct.

Obviously reasonable answer 2:

 if ([super respondsToSelector:_cmd]) [super d]; 

This does not work, because the implementation of NSObject -respondsToSelector will find the implementation in Child and will return YES in all cases.

Obvious reasonable answer 3:

 if ([[self superclass] instancesRespondToSelector:_cmd]) [super d]; 

This works if and only if the superclass knows that it always implements -d; if instances dynamically determine if this method is present, this method will not work. Better than 1, that it will receive static changes in the implementation of Parent at runtime.

Obviously reasonable answer 4:

 @try { [super d]; } @catch (NSException *exception) { NSString *templateReason = [NSString stringWithFormat: @"-[%@ %@]: unrecognized selector sent to instance %p" ,NSStringFromClass([self superclass]) ,NSStringFromSelector(_cmd) ,self]; if (![exception.reason isEqualToString:templateReason]) @throw exception; } 

The performance of this is bad if the method does not exist in the superclass, because calculating templateReason and then comparing it with the cause of the exception is expensive.

This mechanism is fragile because the string format of the reason for the exception in this case may be changed in a future version of the SDK or runtime.

+6
source share
3 answers

None of this is needed.

If you subclass a class or another, you already need to know if you are replacing or complementing the behavior.

In other words, if an implementation exists and you want it to run differently, you do not call super.

If the implementation does not exist, you do not call super.

If the implementation exists, but you want to complement it, you call super.

Addendum:

The connection, which may change at any time, is not relevant to your question; important if the interface changes.

If the interface is constantly changing, the coefficients are good, the class is an extremely poor candidate for subclasses or even uses.

+5
source

Unfortunately, I'm not sure if any of these answers are good. Unfortunately, this boils down to the goal - it cannot even be intended to call a superclass method, sometimes overriding a method consists in replacing the method, and not on binding your functionality on top of the superclass functionality.

It comes down to reading the documentation and choosing the right approach.

If it is a structure that you are implementing and want to use a consistent approach, then 2 or 3 should be fine. 1 and 4 rely on exceptions - which are not really intended to be used for anything other than the truly exceptional problems in objective-c.

+1
source

In lens c, you can define the methods in the required or optional protocols, but you are never sure that the class corresponding to the protocol actually implements this protocol.

Therefore, you always need to check if the instance is responding to the protocol.
I would choose option 2, this is the most elegant. When you make an optional protocol method in the future, this will still be the right decision.

Option 4 I personally find a lot of Java-ish.

-1
source

Source: https://habr.com/ru/post/902202/


All Articles