2

通常,您定义 init 或 initWith... 方法并在方便的构造函数中调用它们,如下所示:

@implementation MyClass1 : NSObject
@synthesize n, s;

-(id)init
{
    self = [super init];
    if (self) {
        self.n = 1;
    }
    return self;
}

-(id)initWithString:(NSString *)s
{
    self = [self init];
    if (self) {
        self.s = s;
    }
    return self;
}

+(id)myClass
{
    return [[self alloc] init];
}

+(id)myClassWithString:(NSString *)s
{
    return [[self alloc] initWithString:s];
}
@end

但我认为可以在不定义 init 或 initWith... 方法的情况下定义方便的构造函数,如下所示:

@implementation MyClass2
@synthesize n, s;

+(id)myClass
{
    MyClass2 *obj = [[self alloc] init];
    obj.n = 1;
    return obj;
}

+(id)myClassWithString:(NSString *)s
{
    MyClass2 *obj = [self myClass];
    obj.s = s;
    return obj;
}

@end

在不定义 init 方法的情况下定义方便的构造函数是不好的做法吗?
如果这是不好的做法,你能告诉我缺点或问题吗?

4

3 回答 3

1

我不确定这是否真的是一种不好的做法。通常,当我编写便利构造函数时,它们看起来像这样:

+ (FSClub *)clubWithXMLElement:(SMXMLElement *)element;
{
    FSClub *club = [[FSClub alloc] init];
    if (club)
    {
        club.identifier = [element integerValueWithPath:@"id"];
        club.name       = [element valueWithPath:@"naam"];
        club.referer    = [element URLWithPath:@"referer"];
    }
    return club;
}

该代码仍然考虑到可能的内存问题(初始化失败),例如在“正常”初始化构造函数中。只有初始化成功时才会设置值。

接口文件定义如下:

@interface FSClub : NSObject

@property (nonatomic, assign, readonly) NSInteger identifier;
@property (nonatomic, copy, readonly)   NSURL    *referer;
@property (nonatomic, copy, readonly)   NSString *name;

+ (FSClub *)clubWithXMLElement:(SMXMLElement *)element;

@end

请注意,这些属性是只读的。我更喜欢创建不可变对象,因为它们在线程代码中更容易处理。在这种情况下设置属性的唯一方法是使用便捷构造函数。

当我创建便利构造函数时,这些通常是我用来实例化对象的唯一方法。也就是说,-init大部分时间不会使用该方法。此外,即使您不使用它们,编写大量初始化程序也会占用大量开发人员时间。我不会创建我不使用的方法。

当您创建代码作为框架的一部分时- 您与许多不认识的人共享的代码 -在这种情况下,您可能想要编写便利构造函数以及所有普通构造函数,因为您不能确保代码将如何在人们自己的项目中使用。例如,在紧密循环中使用便利构造函数创建大量对象可能对性能不利,因为这些对象被添加到自动释放池中。我认为在 ARC 场景中也是如此。在这种情况下,可以选择使用“普通”构造函数来创建对象。

于 2012-08-31T08:04:18.743 回答
0
//I think it is BAD. First of all, you confused CLASS and OBJECT, you get an object like this

//    [[CLASSNAME alloc] init];

//not like this: 

//    [[OBJECT alloc] init];

//so, what you want to do shall be like this:

//    +(id)myClass
//    {
//        MyClass2 *obj = [[[self class] alloc] init];
//        obj.n = 1;
//        return obj;
//    }

请首先忽略,感谢@W'rkncacnter。

但是,在这里您返回的是您自己拥有的对象而没有自动释放,不建议这样做。

也许您真正想要的是工厂方法之类的东西?

+(id)myObjectWithString:(NSString *)string
{
    MyClass2 *obj = [[[MyClass2 alloc] init] autorelease];
    obj.s = string;
    return obj;
}
于 2012-08-31T07:46:08.663 回答
0

像你一样做MyClass1它可以更容易地定义一个指定的初始化器。苹果推荐这些;它们有助于减少代码重复。

于 2012-08-31T08:36:10.333 回答