Objective-C:从超类获取子类列表

Lit*_*jon 11 objective-c

在Objective-C中有一种方法可以询问类是否存在任何子类实现.

我有一个Base类,它有多个子类.我想循环遍历所有子类并在每个子类上执行类选择器.

编辑:

我有一组可以处理某些类型数据的类.每个处理器都对一个基类进行子类化,该基类提供每个处理器所需的方法.

每个类都知道它可以处理哪些数据,而某些类可以比其他类更好地处理某些类型的数据.

我想在每个类上都有一个类方法,它会向工厂类提供一个响应,表示我可以处理该数据,并指出它可以处理它的程度.

然后工厂根据哪个类说它可以最好地处理数据来决定实例化哪个类.

我也从2009年发现了这个问题(我在发布之前进行了搜索,但没有发现任何内容)在Obj-C中发现给定类的子类.

编辑2:

+ (void)load方法看起来是我正在寻找的完美解决方案.所以我现在有以下内容:

+ (void)registerSubclass:(Class)subclass {
    NSLog(@"Registered %@", subclass);
}
Run Code Online (Sandbox Code Playgroud)

在我的基类中,这是我的潜艇.

+(void)load {
    [BaseSwitch registerSubclass:[self class]];
}
Run Code Online (Sandbox Code Playgroud)

现在,这将显示每个子类的调试消息.

我的下一个问题是(可能是一个愚蠢的问题),如何存储在registerSubclass方法中注册的类.有没有办法让我可以在以后阅读的类变量?

编辑3:

在这里找到一些示例代码Cocoa中一个简单,可扩展的HTTP服务器

这给我留下了以下内容,看起来很简单,看起来很简单.但我想我会把它放在这里供将来参考.

@implementation BaseSwitch

static NSMutableArray *registeredSubclasses;

+ (void)registerSubclass:(Class)subclass {
    if (registeredSubclasses == nil) {
        registeredSubclasses = [[NSMutableArray alloc] init];
    }

    [registeredSubclasses addObject:subclass];

    NSLog(@"Registered %@", subclass);
}

+ (void)logSubclasses {
    for (int i = 0; i < [registeredSubclasses count]; i++) {
        NSLog(@"%@", [registeredSubclasses objectAtIndex:i]);
    }
}

@end
Run Code Online (Sandbox Code Playgroud)

感谢大家的建议,我会在几天之内将这个问题留下来,因为其他问题出现了.

Tho*_*asW 10

此函数为您提供类的所有子类:

#import <objc/runtime.h>

NSArray *ClassGetSubclasses(Class parentClass)
{
  int numClasses = objc_getClassList(NULL, 0);
  Class *classes = NULL;

  classes = (__unsafe_unretained Class *)malloc(sizeof(Class) * numClasses);
  numClasses = objc_getClassList(classes, numClasses);

  NSMutableArray *result = [NSMutableArray array];
  for (NSInteger i = 0; i < numClasses; i++)
  {
    Class superClass = classes[i];
    do
    {
      superClass = class_getSuperclass(superClass);
    } while(superClass && superClass != parentClass);

    if (superClass == nil)
    {
      continue;
    }

    [result addObject:classes[i]];
  }

  free(classes);

  return result;
}
Run Code Online (Sandbox Code Playgroud)

取自可可与爱.


Sul*_*han -8

你永远不能列出一个类的子类。在(几乎)任何编程语言中。这是面向对象编程的基本属性之一。

考虑更改您的对象模型。

您可能想要的是创建一个抽象类和不同的子类,但您不应该从抽象类访问子类。您应该创建另一个对象(工厂类)来注册子类并在需要时选择合适的子类。

请注意,您无法从类本身有效地注册类。要执行类代码,必须首先加载该类。这意味着,您必须在其他类中导入其标头,这意味着您实际上是通过导入其标头来注册该类。有两种可能的解决方案:

  1. 您的工厂类必须知道所有子类的名称(在编译时或读取某些配置文件时)。
  2. 您的工厂类有一个方法,任何人都可以向该方法传递要注册的类的名称。如果您希望外部库注册新的子类,这是正确的解决方案。然后你可以将子类注册代码放入库的主头中。

  • 不可能列出一个类的每个可能的子类,但 OOP 的属性不阻止列出给定时间点给定程序中存在的子类。在 ObjC 中,这可以通过 objc_getClassList() 来完成,然后内省类。这不是一个好主意,但 OOP 并没有禁止它。 (5认同)