Objective c 在Obj-C中发现给定类的子类

Objective c 在Obj-C中发现给定类的子类,objective-c,cocoa,reflection,Objective C,Cocoa,Reflection,有没有办法在运行时发现给定类中存在哪些子类 编辑:从目前的答案来看,我想我需要进一步澄清我想做的事情。我知道这在可可中不是一种常见的做法,可能会有一些警告 我正在使用动态创建模式编写解析器。(参见Buck和Yacktman的《Cocoa设计模式》一书,第5章。)基本上,解析器实例处理堆栈,并实例化知道如何执行某些计算的对象 如果我可以获得MYCommand类的所有子类,例如,我可以向用户提供可用命令的列表。此外,在第5章的示例中,解析器有一个替换字典,因此可以使用+、-、*和/等运算符。(它们被

有没有办法在运行时发现给定类中存在哪些子类

编辑:从目前的答案来看,我想我需要进一步澄清我想做的事情。我知道这在可可中不是一种常见的做法,可能会有一些警告

我正在使用动态创建模式编写解析器。(参见Buck和Yacktman的《Cocoa设计模式》一书,第5章。)基本上,解析器实例处理堆栈,并实例化知道如何执行某些计算的对象


如果我可以获得
MYCommand
类的所有子类,例如,我可以向用户提供可用命令的列表。此外,在第5章的示例中,解析器有一个替换字典,因此可以使用+、-、*和/等运算符。(它们被映射到
MYAddCommand
等)对我来说,这些信息似乎属于
MyCommand
子类,而不是解析器实例,因为它有点违背了动态创建的思想。

不是直接的,不可以。但是,您可以获得在运行时注册的所有类的列表,以及查询这些类的直接超类。请记住,这不允许您在继承树上查找类的所有祖先,只允许查找直接超类

您可以使用获取在运行时注册的
Class
对象列表。然后,您可以在该数组上循环,并对这些
对象调用
[NSObject superclass]
,以获取它们的超类“
对象。如果由于某种原因,您的类不使用
NSObject
作为其根类,则可以使用


我还应该提到,如果您觉得有必要进行此类发现,您可能会错误地考虑应用程序的设计。很可能还有另一种更为传统的方式来完成您试图完成的任务,而不涉及对Objective-C运行时的内省。

Marc和bbum在金钱上达成了共识。这通常不是一个好主意


然而,我们的CocoaHeads wiki上有这样的代码:

与其尝试自动注册MYCommand的所有子类,为什么不将问题一分为二呢

首先,提供用于注册类的API,类似于
+[MYCommand registerClass::

然后,在MYCommand中创建代码,这意味着任何子类都将自动注册自己。比如:

@implementation MYCommand
+ (void)load
{
    [MYCommand registerClass:self];
}
@end

在我的运行时浏览器项目中,有一段代码包含一个-subclassNamesForClass:method。查看
RuntimeReporter.[hm]
文件。

马特·加拉赫(Matt Gallagher)于上周五刚刚发布了另一种方法。

我想说得更有力一些;如果您认为需要在生产代码中这样做,那么很可能是做错了。向下看的继承内省非常少见,这也是运行时不直接支持它的原因。你想做什么?@bbum我已经添加了我想做的描述。你还认为我做错了吗?在不寻找子类的情况下,我很难想出另一种方法来实现这一点;在执行此类操作时,最终会导致类按照以前从未初始化过的顺序进行+初始化。这不会导致问题,但有时会因为系统类中的依赖关系而导致问题,这些依赖关系可能会在不同版本之间发生变化……链接代码的描述特别指出,这种方法不调用
+initialize
,虽然我还没有尝试过,但似乎是正确的。这看起来确实是正确的方法。特别是因为文档提到类的
+load
方法在其所有超类的
+load
方法之后被调用。多亏了其他人也提供了答案,他们的答案也很棒。MyCommand的子类不会在他们的超类上调用+load+load只在实现它的类中被调用。奇怪的是,这么长时间才有人纠正我!我大体上同意这里的答案,自动注册是一个坏主意,应该手动处理多一点。谢谢,这是一个有趣的工具添加到我的腰带。不过我还是同意Mike在这个特殊情况下的做法。我注意到@NSResponder发布的链接已断开。对于那些寻找通过类层次结构循环的方法的人,我编写了一个使用类似方法的。如果您需要更深入地了解如何迭代子类层次结构,那么它可能会很有用。我希望有帮助!