2012-08-31 55 views
2

通常情況下,您可以定義init或initWith ...方法,並呼籲他們方便的構造像這裏面:定義和使用方便的構造函數而不定義init方法是不好的做法?

@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方法嗎?
如果不好的做法,你能告訴我的缺點或問題嗎?

+0

我認爲這是一個約定的問題。一般來說,遵循慣例是一種很好的商業慣例。只要確保遵循所有權和保留/釋放的命名約定,當您不使用ARC時,這當然更重要。順便說一句,你在「更好」的構造函數中調用'init'。:) –

回答

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方法大部分時間不會使用。另外,即使你不使用它們,也要寫很多初始化程序,這需要很多開發人員的時間。我不會創建我不使用的方法。

當您將代碼創建爲框架的一部分時-code與許多您不認識的人分享的代碼在這種情況下,您可能希望編寫便捷構造函數以及所有常規構造函數,因爲你不能確定代碼將如何用於人們自己的項目。例如,在緊密循環中使用便捷構造函數創建大量對象可能會對性能造成影響,因爲對象會添加到autorelease池中。我認爲這在ARC場景中也是如此。在這種情況下,人們可以選擇使用「普通」構造函數來創建對象。

+0

感謝您的明確和有益的答案! –

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; 
} 
+0

在類方法中,'self' _is_類,並且將其稱爲'[self class]'是多餘且不必要的。 '+(id)convenienceConstructor {return [[[self alloc] init] autorelease]; ''是正確的。 –

+0

@ W'rkncacnter你是對的,謝謝 – fvwmer

0

這樣做,就像您使用MyClass1所做的那樣,可以更輕鬆地定義指定的初始化程序。 Apple recommends these;它們有助於減少代碼重複。

相關問題