因为在 Objective-C 中,私有(private)方法并不是真正私有(private)的(方法调度机制不区分私有(private)方法和公共(public)方法),子类很容易覆盖父类(super class)的私有(private)方法(更多关于这个在 Cocoa Coding Guidelines )。
然而,要检测到这一点并不容易。我正在寻找可以帮助我解决此问题的现成工具。
这不能简单地是一个静态分析工具,因为接口(interface)中没有暴露私有(private)方法。该工具要么必须检查二进制文件,要么在运行时解决这个问题。根据我的说法,此工具必须执行类似于以下操作的操作:
通过检查 header 获取项目使用的每个类的所有公共(public)方法的列表,然后执行步骤 2 或步骤 3
通过检查二进制文件获取覆盖的私有(private)方法
a) 读取应用程序二进制文件及其链接的所有动态库,以获取应用程序使用的每个类定义的所有方法的列表。
b) 其中,步骤1中未找到的方法为私有(private)方法。
c) 遍历类层次结构并找出覆盖父类(super class)私有(private)方法的子类
在运行时获取重写的私有(private)方法
a) 运行应用
b) 使用 Objective-C 运行时方法,我们可以获得为所有类定义的所有方法。
c) 同样,在步骤 1 中未找到的方法是私有(private)方法
d) 遍历类层次结构并找出覆盖父类(super class)私有(private)方法的子类
这并不总是有效——因为类和方法可以在运行时添加/删除,一些情况会被遗漏(最值得注意的是,NSManagedObject
子类,其中提供了核心数据属性的方法运行)。不过没关系,我愿意忍受这种限制。
我相信使用 libclang 很有可能实现这一目标、otool
或 nm
等目标文件检查工具,以及 Objective-C 运行时,但是是否有现成的工具可以完成所有这些工作?
注意:我不是在寻找缓解此问题的方法;如何检测这种情况。
最佳答案
您可以通过进入 Objective-C 运行时来执行此操作。
参见objc/runtime.h,即:
/**
* Describes the instance methods implemented by a class.
*
* @param cls The class you want to inspect.
* @param outCount On return, contains the length of the returned array.
* If outCount is NULL, the length is not returned.
*
* @return An array of pointers of type Method describing the instance methods
* implemented by the class—any instance methods implemented by superclasses are not included.
* The array contains *outCount pointers followed by a NULL terminator. You must free the array with free().
*
* If cls implements no instance methods, or cls is Nil, returns NULL and *outCount is 0.
*
* @note To get the class methods of a class, use \c class_copyMethodList(object_getClass(cls), &count).
* @note To get the implementations of methods that may be implemented by superclasses,
* use \c class_getInstanceMethod or \c class_getClassMethod.
*/
OBJC_EXPORT Method *class_copyMethodList(Class cls, unsigned int *outCount)
__OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
关于objective-c - 如何确定父类(super class)私有(private)方法是否在 Objective-C 中被重写?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22059393/