8

有没有办法从子类中动态检测它是否覆盖其父方法?

Class A {
    - methodRed;
    - methodGreen;
    - methodBlue;
}
Class B inherits A {
    - methodRed;
}

从上面的示例中,我想知道 B 类是否能够动态检测到仅-methodRed;被覆盖。

我想知道这种方法与其他一些可能性的原因是因为我有几十个自定义视图将改变那里的外观。如果我可以动态检测被覆盖的方法而不是跟踪,那么代码会少很多。

4

2 回答 2

17

这很容易测试:

if (method_getImplementation(class_getInstanceMethod(A, @selector(methodRed))) ==
    method_getImplementation(class_getInstanceMethod(B, @selector(methodRed))))
{
    // B does not override
}
else
{
    // B overrides
}

我确实想知道知道 B 是否覆盖 A 上的方法是有帮助的,但是如果您想知道,这就是您找到的方法。

还可能值得注意:在最严格的术语中,上面的代码确定 B 上选择器的实现是否与 A 上选择器的实现不同。如果您有像 A > X > B 这样的层次结构,并且 X 覆盖了选择器,这仍然会报告 A 和 B 之间的不同实现,即使 B 不是覆盖类。如果您想具体了解“B 是否覆盖此选择器(不管其他任何内容)”,您会想要这样做:

if (method_getImplementation(class_getInstanceMethod(B, @selector(methodRed))) ==
    method_getImplementation(class_getInstanceMethod(class_getSuperclass(B), @selector(methodRed))))
{
    // B does not override
}
else
{
    // B overrides
}

很明显,这提出了一个问题“B 选择器的实现是否与其超类不同”,这就是您所要求的(也许更具体地说)。

于 2013-06-17T12:21:48.433 回答
12

在您的基类中:

BOOL isMethodXOverridden = [self methodForSelector:@selector(methodX)] !=
                           [BaseClass instanceMethodForSelector:@selector(methodX)];

如果你的子类覆盖了methodX,会给你YES。

上面的答案也是正确的,但看起来可能会更好。

于 2013-10-09T16:00:09.320 回答