Objective c 如何将类名作为参数传递给cocoa中的对象工厂?
我在一个对象工厂工作,以跟踪一小部分对象。对象可以是不同的类型,但它们都将响应Objective c 如何将类名作为参数传递给cocoa中的对象工厂?,objective-c,cocoa,constructor,factory,Objective C,Cocoa,Constructor,Factory,我在一个对象工厂工作,以跟踪一小部分对象。对象可以是不同的类型,但它们都将响应createInstance和reset。无法从公共基类派生对象,因为其中一些对象必须从内置的cocoa类派生,如NSView和NSWindowController 我希望能够创建任何合适对象的实例,只需将所需的类名传递给我的工厂,如下所示: myClass * variable = [factory makeObjectOfClass:myClass]; makeObjectOfClass:方法如下所示: - (id
createInstance
和reset
。无法从公共基类派生对象,因为其中一些对象必须从内置的cocoa类派生,如NSView
和NSWindowController
我希望能够创建任何合适对象的实例,只需将所需的类名传递给我的工厂,如下所示:
myClass * variable = [factory makeObjectOfClass:myClass];
makeObjectOfClass:
方法如下所示:
- (id)makeObjectOfClass:(CLASSNAME)className
{
assert([className instancesRespondToSelector:@selector(reset)]);
id newInstance = [className createInstance];
[managedObjects addObject:newInstance];
return newInstance;
}
是否有一种方法可以将类名传递给方法,就像我在上面使用makeObjectOfClass:
的(CLASSNAME)CLASSNAME
参数所做的那样
为了完整性,下面是我想要管理所有对象的原因。我希望能够通过调用[factory reset],一次性重置整套对象代码>
- (void)reset
{
[managedObjects makeObjectsPerformSelector:@selector(reset)];
}
听起来你想要的是:
- (id)makeObjectOfClassNamed:(NSString *)className
{
Class klass = NSClassFromString(className);
assert([klass instancesRespondToSelector:@selector(reset)]);
id newInstance = [klass createInstance];
[managedObjects addObject:newInstance];
return newInstance;
}
这将假定一个名为+createInstance
的类方法。或者您可以使用[[klass alloc]init]
称之为:
MyClass *variable = [factory makeObjectOfClassNamed:@"MyClass"];
根据您尝试执行的操作,传递类对象可能比传递字符串更好,例如:
MyClass *variable = [factory makeObjectOfClass:[MyClass class]];
动态指定一个类非常容易,事实上,您可以通过它的名称引用它:
id string = [[NSClassFromString(@"NSString") alloc] initWithString:@"Hello!"];
NSLog( @"%@", string );
另一个技巧是,我会避免使用术语“托管对象”,因为大多数其他Cocoa程序员会从核心数据中将其理解为NSManagedObject。您可能还发现使用全局NSNotification(所有可重置对象都订阅)而不是管理不同类型对象的集合更容易,但您比我更容易做出决定。您可以使用函数NSClassFromString将字符串转换为类
Class classFromString = NSClassFromString(@"MyClass");
但在您的情况下,最好直接使用类对象
MyClass * variable = [factory makeObjectOfClass:[MyClass class]];
- (id)makeObjectOfClass:(Class)aClass
{
assert([aClass instancesRespondToSelector:@selector(reset)]);
id newInstance = [aClass createInstance];
[managedObjects addObject:newInstance];
return newInstance;
}
其他答案中缺少的一点答案是,您可以定义一个包含+createInstance
和+reset
方法的@protocol
。我有一个更好的教程,请查看
谢谢你的提示!我正计划使用一个协议,但我觉得没有必要在问题中提及它。我在迈克尔·蔡(Michael Tsai)和马特·加拉赫(Matt Gallagher)的答案之间左右为难。我对两者都投了更高的票,因为两者都提到了“Class”的用法,这正是我想要的。最后,我选择了Matt的答案,因为它强调“Class”而不是“ClassFromString”,而且在编辑之前,它是第一个提到“Class”的用法的。@Ned Batchelder:谢谢你更改标记。出于某种原因,“objective-c”在我向问题添加标记时出现的标记下拉列表中显示的项目比“objective-c”多得多(大约200个),但我现在看到“objective-c”已重定向到“objective-c”@eJames:您的问题显示-reset被发送到实例,而不是类对象,因此我认为[aClass respondsToSelector:@selector(重置)]在Matt Gallagher中,他的回答是错误的。@Michael Tsai:很好的回答!我不会注意到。Matt一定复制了我的示例,其中的方法调用也不正确。谢谢提醒。我已将问题中的代码改为使用InstanceRespondtoSelector。“类”类型和[MyClass类]这正是我想要的。谢谢!Michael Tsai指出[aClass respondsToSelector:@selector(reset)]行应该改为[aClass InstanceRespondsToSelector:@selector(reset)]。我正在修改我的问题,您可能希望在回答中也这样做。谢谢您的回答。我将使用[MyClass类]您在编辑中提到的方法。除非您是为Objective-C++编译,否则您可以将变量命名为“class”。关于NSManagedObject的观点很好。我将更改我的问题以避免可能的混淆。