2011-08-11 29 views
6

Tôi đã nhìn thấy một số mã mẫu đã khiến tôi băn khoăn về việc gọi trình khởi tạo được chỉ định trong các lớp siêu. Nói rằng tôi có một số mã này:Các lớp con có nên gọi trình khởi tạo được chỉ định trong lớp siêu ngay lập tức không?

@interface NewTableViewCell : UITableViewCell { 
} 
@end 

@implementation NewTableViewCell 
- (id) initWithFrame: (CGRect)frame { 
    self = [super initWithFrame:frame]; 
    if (self) { 
     // Do some stuff 
    } 
return self; 
} 
@end 

Lưu ý rằng initWithFrame là khởi tạo dành riêng cho UIView, không UITableView. Mã này có luôn luôn được gọi là [UITableViewCell initWithStyle:reuseIdentifier:] hay không tùy thuộc vào ý định của người lập trình?

+0

Bạn có nghĩa là [UITableviewCell initWithStyle: reuseIdentifier:] – Joe

Trả lời

7

Khi phân lớp, hướng dẫn là trình khởi tạo được chỉ định phải gọi trình khởi tạo được chỉ định của siêu lớp.

Một nguyên tắc khác là lớp con cần ghi đè trình khởi tạo được chỉ định của lớp cha để gọi trình khởi tạo được chỉ định mới.

Nếu UITableViewCell sau chủ trương này (và nó, tôi thử nghiệm với sự giúp đỡ của một chủng loại), nó quan trọng hơn lớp cha của nó initializer định (UIView 's initWithFrame:) để gọi initializer định mới (initWithStyle:reuseIdentifier:). Do đó, nếu bạn gọi initWithFrame: trên UITableViewCell, số này sẽ gọi initWithStyle:reuseIdentifier:, lần lượt sẽ gọi initWithFrame: trên super (UIView).

Vì vậy, nó sẽ cần một cuộc gọi phương thức bổ sung nhưng cuối cùng nó sẽ đi qua initWithStyle:reuseIdentifier:. Một lần nữa, thực hành tốt nhất là trình khởi tạo được chỉ định phải gọi trình khởi tạo được chỉ định của lớp siêu và bất kỳ trình khởi tạo nào khác không phải là trình khởi tạo được chỉ định phải gọi trình khởi tạo được chỉ định. Từ "The Designated Initializer":

chung nguyên tắc: Các initializer được chỉ định trong một lớp phải, thông qua một thông điệp tới siêu, gọi initializer được chỉ định trong một lớp cha.

Trình khởi tạo được chỉ định được ghép nối với nhau thông qua các thư đến siêu, trong khi các phương thức khởi tạo khác được kết nối với các trình khởi tạo được chỉ định thông qua các thư đến chính chúng.

+0

Nếu trình khởi tạo được chỉ định phải gọi trình khởi tạo được chỉ định của lớp siêu, các trình khởi tạo khác phải làm gì? Giả sử tôi đã quyết định rằng trình khởi tạo được chỉ định của khung nhìn của tôi sẽ là một phương thức được gọi là điểm initWithPoint: (CGPoint). Việc thực hiện initWithFrame sẽ là gì? Nó sẽ gọi trình khởi tạo được chỉ định với một điểm mặc định? Nó có làm gì khác không? – csano

+0

@ j0k trình khởi tạo khác có nghĩa vụ phải gọi trình khởi tạo được chỉ định. Bạn không bắt buộc phải cung cấp phương thức 'initWithFrame', nhưng nếu bạn làm thế, tôi đoán bạn có thể gọi trình khởi tạo được chỉ định của bạn với một điểm mặc định.Nếu bạn không cung cấp phương thức và bạn bắt đầu một cá thể mới thông qua 'initWithFrame' (được định nghĩa trong một lớp cha), thì trình khởi tạo được chỉ định của bạn cuối cùng sẽ được gọi và cá thể sẽ được khởi tạo đúng cách. – albertamg

+0

Cảm ơn câu trả lời. Có điều gì đặc biệt chúng ta cần phải làm để chỉ định một initializer như là một intializer được chỉ định khác hơn có lẽ đề cập đến điều này trong tài liệu? – csano

1

Tôi đồng ý điều đó tùy thuộc vào cố gắng của người lập trình nhưng trình mã nên luôn cố gắng và sử dụng trình khởi tạo được chỉ định. Hãy suy nghĩ về initializers bạn có thể đã viết, họ có thể làm công việc bổ sung cho đối tượng của bạn ở trong một nhà nước có thể sử dụng hoặc mong muốn. Nếu bạn đang ghi đè trình khởi tạo như bạn đang làm trong ví dụ của mình, bạn cũng nên gọi bộ khởi tạo ghi đè. Nếu đó là một phương thức init tùy chỉnh thì bạn sẽ muốn gọi trình khởi tạo được chỉ định bởi vì đối với UITableViewCell đó là cách duy nhất để thiết lập lại công cụ reuseIdentifier.

//Override initWithFrame 
//Fine although it may not (should not) get called for a UITableViewCell 
- (id) initWithFrame: (CGRect)frame { 
    self = [super initWithFrame:frame]; 

//Design a custom initializer to gather parameters for supers default initializer 
-(id)initWithCustomObject:(id)object style:(UI..Style)style reuseIdentifier:(NSString*)rid { 
    //This should call initWithStyle:reuseIdentifier: 
Các vấn đề liên quan