2012-08-17 29 views
6

Giả sử phương pháp -init của chúng tôi chỉ gọi các thư trên self, tại sao việc kiểm tra xem self != nil nếu nhắn tin nil có hiệu lực không?Tại sao chọn tự! = Nil in -init khi nhắn tin nil không có hiệu lực?

Hãy nói rằng chúng ta có một khởi tạo như sau:

- (id)init 
{ 
    self = [super init]; 
    if (self) { 
     [self doThis]; 
     [self setFoo:@"Bar"]; 
    } 

    return self; 
} 

Thay vì kiểm tra self, chúng ta có thể viết:

- (id)init 
{ 
    self = [super init]; 
    [self doThis]; 
    [self setFoo:@"Bar"]; 

    return self; 
} 

Bây giờ nếu vì một lý do [super init] lợi nhuận nil, sẽ không có sự khác biệt trong kết quả của phương pháp theo như tôi biết. Tại sao chúng ta liên tục thực hiện kiểm tra này?

Trả lời

7

Bạn có thể gửi thư đến số không, nhưng bạn không thể truy cập các biến mẫu của nil. Bạn sẽ nhận được một ngoại lệ EXC_BAD_ACCESS.

Hãy xem xét một lớp học có các biến Ví dụ:

@implementation MyObject { 
    int instanceVariable; 
} 

- (id)init { 
    self = [super init]; 
    instanceVariable = 7; 
    return self; 
} 

gì xảy ra nếu [super init] lợi nhuận Nil trong ví dụ này? Bạn sẽ cố gắng truy cập vào đó instanceVariable tắt của một con trỏ null và bạn sẽ nhận được một ngoại lệ.

Ngay cả khi bạn không truy cập bất kỳ biến mẫu nào, những thứ khác chắc chắn có thể sai nếu bạn không kiểm tra self == nil. Bạn có thể dễ dàng bị rò rỉ malloc bộ nhớ hoặc bộ xử lý tệp được phân bổ hoặc tự chuyển cho một số phương thức không mong đợi.

Câu trả lời khác cho rằng bạn có thể làm rò rỉ các đối tượng nếu bạn không kiểm tra số không. Ví dụ:

@implementation MyObject 

@synthesize someProperty; // assume it's an NSObject * 

- (id)init { 
    self = [super init]; 
    [self setSomeProperty:[[NSObject alloc] init]]; 
    return self; 
} 

này sẽ không bị rò rỉ dưới ARC, ngay cả khi self là con số không. Dưới tính năng tham chiếu thủ công (MRC), ví dụ này sẽ làm rò rỉ liệu self có phải là không hoặc không, vì không có gì để cân bằng số lần giữ lại +1 từ số [NSObject alloc].

Cách thích hợp để làm điều đó dưới MRC là thế này:

- (id)init { 
    self = [super init]; 
    [self setSomeProperty:[[[NSObject alloc] init] autorelease]]; 
} 

hay này:

- (id)init { 
    self = [super init]; 
    NSObject *object = [[NSObject alloc] init]; 
    [self setSomeProperty:object]; 
    [object release]; 
    return self; 
} 

Cả những sẽ bị rò rỉ, cho dù self là con số không hay không.

Nếu bạn bỏ qua các phương pháp setter, như thế này, bạn sẽ chỉ sụp đổ nếu self là con số không:

- (id)init { 
    self = [super init]; 
    _someProperty = [[NSObject alloc] init]; 
    return self; 
} 
+0

Đó đúng hơn là tín hiệu - C không có ngoại lệ. –

+1

+1 mặc dù, câu trả lời tuyệt vời. –

+0

Đó là ngoại lệ CPU, không phải ngoại lệ C++. Kiểm tra '/ usr/include/mach/exception_types.h'. –

0

Nếu [siêu init] đã lần lượt trở lại con số không, sau đó bạn sẽ kết thúc có thể phân bổ hơn các đối tượng sẽ không bao giờ được sử dụng, vì khi bạn trả về tự, bạn sẽ trả về nil; Vì vậy, những đồ vật đó sẽ không được giải phóng.

+0

Vì vậy, cuối cùng @rob là đúng - đây không phải là lý do thực sự. –

+0

@ user1606088 Đừng nản lòng. Đây là một vấn đề khá tinh tế. –

Các vấn đề liên quan