Como eu posso passar um nome de classe como um argumento para uma fábrica de objeto no cacau?
-
10-07-2019 - |
Pergunta
Eu estou trabalhando em uma fábrica de objeto para manter o controle de uma pequena coleção de objetos. Os objetos podem ser de diferentes tipos, mas todos eles vão responder a createInstance
e reset
. Os objetos não pode ser derivada de uma classe base comum porque alguns deles terão que derivar de classes internas de cacau como NSView
e NSWindowController
.
Eu gostaria de ser capaz de criar instâncias de qualquer objeto adequado, simplesmente passando o nome da classe desejada para a minha fábrica da seguinte forma:
myClass * variable = [factory makeObjectOfClass:myClass];
O método makeObjectOfClass:
seria algo parecido com isto:
- (id)makeObjectOfClass:(CLASSNAME)className
{
assert([className instancesRespondToSelector:@selector(reset)]);
id newInstance = [className createInstance];
[managedObjects addObject:newInstance];
return newInstance;
}
Existe uma maneira de passar um nome de classe para um método, como eu fiz com o argumento (CLASSNAME)className
para makeObjectOfClass:
acima?
Por uma questão de exaustividade, aqui é por isso que quero para gerenciar todos os objetos. Eu quero ser capaz de redefinir o conjunto completo de objetos em um tiro, chamando [factory reset];
.
- (void)reset
{
[managedObjects makeObjectsPerformSelector:@selector(reset)];
}
Solução
Você pode converter uma string para uma classe usando a função: NSClassFromString
Class classFromString = NSClassFromString(@"MyClass");
No seu caso, porém, você seria melhor fora usando a classe objetos diretamente.
MyClass * variable = [factory makeObjectOfClass:[MyClass class]];
- (id)makeObjectOfClass:(Class)aClass
{
assert([aClass instancesRespondToSelector:@selector(reset)]);
id newInstance = [aClass createInstance];
[managedObjects addObject:newInstance];
return newInstance;
}
Outras dicas
Eu tenho direito de ter um tutorial sobre isso, por favor check-out https://appengineer.in/ 2014/03/13 / send-class-name-como-um-argumento-in-ios /
É muito fácil para especificar dinamicamente uma classe, na verdade, você pode apenas fazer referência a ela por ele é nome:
id string = [[NSClassFromString(@"NSString") alloc] initWithString:@"Hello!"];
NSLog( @"%@", string );
Uma outra dica, gostaria de evitar usando a nomenclatura 'conseguiu objeto' já que a maioria outros programadores de cacau vai ler isso como NSManagedObject, do Core Data. Você também pode achar que é mais fácil usar um NSNotification global (que todos os seus objetos de reset-poder subscrever) em vez de gerenciar uma coleção de diferentes tipos de objetos, mas você está mais informado para tomar essa decisão que eu.
O bit da resposta ausente das outras respostas é que você pode definir um @protocol
contendo seus métodos +createInstance
e +reset
.
Parece que você quer algo como:
- (id)makeObjectOfClassNamed:(NSString *)className
{
Class klass = NSClassFromString(className);
assert([klass instancesRespondToSelector:@selector(reset)]);
id newInstance = [klass createInstance];
[managedObjects addObject:newInstance];
return newInstance;
}
Esta assumiria um método de classe chamado +createInstance
. Ou você pode simplesmente usar [[klass alloc] init]
.
Para chamá-lo:
MyClass *variable = [factory makeObjectOfClassNamed:@"MyClass"];
Dependendo do que você está tentando fazer, que poderia ser melhor para passar em torno de objetos de classe do que cordas, por exemplo:.
MyClass *variable = [factory makeObjectOfClass:[MyClass class]];