Check if subclass overrides a method

2020-06-05 03:18发布

问题:

Is it possible to check whether a subclass implements a method that exists either in its immediate superclass or in some superclass of its superclass, etc?

E.g. I subclass UIView, to make my custom generic view for my app, and then I subclass this custom view. Now some of my subclasses override some method from UIView and some don't. I only want to call this method if it is actually overridden, I do not want the default UIView method being called.

Is there a way to check this, i.e. with a method similar to respondsToSelector:?

Edit: This question is different from the one asked in Objective-C detect if class overrides inherited method because I do not really know or do not want to care which superclass originally implements the method.

回答1:

Based on this answer by Mert Buran.

You can create a simple method to check whether a given object overrides a given selector (method):

-(BOOL)checkIfObject:(id)object overridesSelector:(SEL)selector {

    Class objSuperClass = [object superclass];
    BOOL isMethodOverridden = NO;

    while (objSuperClass != Nil) {

        isMethodOverridden = [object methodForSelector: selector] !=
        [objSuperClass instanceMethodForSelector: selector];

        if (isMethodOverridden) {
            break;
        }

        objSuperClass = [objSuperClass superclass];
    }

    return isMethodOverridden;
}

This can be called as follows:

[self checkIfObject:someObject overridesSelector:@selector(someSelector)];


回答2:

Unfortunately, there is no equivalent to respondsToSelector: that will do precisely this job for you. As you will probably know, respondsToSelector: works in the way that it will return YES as long as the class itself or any of its superclasses implements this method.

But why not just put an empty implementation of the method into your custom subclass, that way you make sure that calling it doesn't have any effect and doesn't call the same method in the superclass. Did you think about this?

Update: While there is no method equivalent to respondsToSelector:, you might want to take a look at the Objective-C Runtime. It's a library that allows you to inspect characteristics of a class during runtime (a bit similar to Java reflections). Check out the reference here.



回答3:

Not the optimal solution but you can keep a boolean member to your UIView subclass (let's call it UIViewSub indicating if the desired behavior is implemented by the class and check that boolean before using the method.

Your subclasses (those inheriting UIViewSub) will set/unset this member accordingly in its construction (i.e if it does override it with implementation or not)



回答4:

Expanding on ZeMoon's answer, I found that there wasn't enough logic to satisfy all cases. I needed to add a check to ensure that instances of the next superclass in the loop implement the specified selector at all. Subclasses of UIView are one example.

while (objSuperClass != Nil) {
    isMethodOverridden = ([objSuperClass instancesRespondToSelector:selector]) && 
                         ([object methodForSelector:selector] !=
                          [objSuperClass instanceMethodForSelector:selector]);

    if (isMethodOverridden) {

    }
}


回答5:

You might ask Why?!