我是这样的类工厂,
@implementation Universe {
NSString *foo;
}
+ (instancetype)universeWithMeaning:(NSString *)meaning
{
return [[self alloc] initUniverseWithMeaning:meaning];
}
- (id)initUniverseWithMeaning:(NSString *)meaning
{
if (self = [super init]) {
foo = meaning;
}
return self;
}
- (void)showMeaning
{
NSLog(@"%@", foo);
}
@end
创建像这样的对象,
Universe *universe = [Universe universeWithMeaning:@"42"];
[universe showMeaning]; // Prints 42
这很好用,但initUniverseWithMeaning:
的方法签名与universeWithMeaning:
的方法签名相同,只不过它是一个允许它将实例变量保存到创建对象的实例方法。
有没有办法解决这个问题,而无需实现initUniverseWithMeaning:
实例方法?
我知道必须在实例方法中才能访问实例变量,所以我一直在试验块。我的想法是将包含实例变量赋值的块传递给类方法,该方法将以某种方式在实例上下文中执行它。
实施,
@implementation Cat {
NSString *lives;
}
+ (Cat *)newCat:(void(^)(void))cat
{
cat(); // **Problem 1**
}
- (void)showLives
{
NSLog(@"%@", lives);
}
@end
用法,
Cat *cat = [Cat newCat:^void (void) {
self.lives = 9; // **Problem 2**
}];
[cat showLives]; // I'd like this to print 9
问题1:如何创建Cat对象并在其中执行cat()?
问题2:如何让self
引用块执行环境中的对象?
无论如何,这比其他任何事情更具好奇心,只有在保存我写alloc
时才会有用(我只需要在initUniverseWithMeaning:
中加入{{1}}的方法原型。 h文件。)
答案 0 :(得分:2)
对于您的问题1和2,您可以试试这个
@interface Cat ()
@property (strong) NSString *lives;
@end
@implementation Cat
+ (Cat *)newCat:(void(^)(Cat *me))cat
{
Cat *newcat = [[self alloc] init];
cat(newcat);
return newcat;
}
- (void)showLives
{
NSLog(@"%@", lives);
}
@end
Cat *cat = [Cat newCat:^(Cat *me) {
me.lives = 9;
}];
[cat showLives]; // print 9
但我看不太多使用它......这不是更简单吗?
Cat *cat = [Cat new];
cat.lives = 9;
[cat showLives];
为您的真正问题
有没有办法解决这个问题,而无需实现initUniverseWithMeaning:instance方法?
+ (instancetype)universeWithMeaning:(NSString *)meaning
{
Universe *universe = [[self alloc] init];
if (universe) universe->foo = meaning;
return universe;
}
答案 1 :(得分:1)
您发布的第一个示例是创建Objective-C工厂方法的正确方法。
Objective-C工厂方法只不过是实例级init方法的类方法包装器。一般来说,每个工厂方法都应该有一个配对的init方法,它采用相同数量和类型的参数。
fooWithBar:(NSString *)bar
应与initWithBar:(NSString *)bar
等配对。
当你有一个带有参数的init
方法时,可能会出现异常,但是你已经为这个方法创建了一些带有默认参数的工厂方法。例如:
- (instancetype)initWithString:(NSString *)string;
+ (instancetype)fooWithString:(NSString *)string {
return [[self alloc] initWithString:string];
}
+ (instancetype)fooWithBar {
return [[self alloc] initWithString:@"bar"];
}
现在,您可以在方法中创建对象,然后修改它,并返回修改后的对象。
例如:
+ (instancetype)fooWithString:(NSString *)string {
Foo *f = [[self alloc] init];
f.str = string;
return f;
}
但老实说,拥有initWithString:
方法更好。
每个类都应该有一个指定的初始化程序,该类的每个对象都应该通过指定的初始化程序。