2010-04-27 32 views
5

Tôi đang chạy vào một vấn đề kỳ lạ trong Objective-C khi tôi có hai lớp bằng cách sử dụng initializers cùng tên, nhưng đối số khác nhau gõ. Ví dụ, giả sử tôi có thể tạo các lớp A và B:Trình khởi tạo Mục tiêu-C có được phép chia sẻ cùng một tên không?

A.h:

#import <Cocoa/Cocoa.h> 

@interface A : NSObject { 
} 

- (id)initWithNum:(float)theNum; 

@end 

giờ sáng:

#import "A.h" 

@implementation A 

- (id)initWithNum:(float)theNum 
{ 
    self = [super init]; 
    if (self != nil) { 
     NSLog(@"A: %f", theNum); 
    } 
    return self; 
} 

@end 

B.h:

#import <Cocoa/Cocoa.h> 

@interface B : NSObject { 
} 

- (id)initWithNum:(int)theNum; 

@end 

Bm:

#import "B.h" 

@implementation B 

- (id)initWithNum:(int)theNum 
{ 
    self = [super init]; 
    if (self != nil) { 
     NSLog(@"B: %d", theNum); 
    } 
    return self; 
} 

@end 

main.m:

#import <Foundation/Foundation.h> 

#import "A.h" 
#import "B.h" 

int main (int argc, const char * argv[]) { 
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 

    A *a = [[A alloc] initWithNum:20.0f]; 
    B *b = [[B alloc] initWithNum:10]; 

    [a release]; 
    [b release]; 

    [pool drain]; 
    return 0; 
} 

Khi tôi chạy này, tôi nhận được kết quả như sau:

2010-04-26 20:44:06.820 FnTest[14617:a0f] A: 20.000000 
2010-04-26 20:44:06.823 FnTest[14617:a0f] B: 1 

Nếu tôi đảo ngược thứ tự của nhập khẩu để nó nhập khẩu Bh trước tiên, tôi nhận được:

2010-04-26 20:45:03.034 FnTest[14635:a0f] A: 0.000000 
2010-04-26 20:45:03.038 FnTest[14635:a0f] B: 10 

Vì lý do nào đó, có vẻ như nó đang sử dụng kiểu dữ liệu được xác định trong bất kỳ @interface nào được đưa vào trước cho cả hai lớp. Tôi đã làm một số bước thông qua trình gỡ rối và thấy rằng con trỏ isa cho cả hai đối tượng a và b kết thúc giống nhau. Tôi cũng phát hiện ra rằng nếu tôi không còn làm cho alloc và init gọi nội tuyến, cả hai khởi tạo dường như để làm việc đúng cách, ví dụ:

A *a = [A alloc]; 
[a initWithNum:20.0f]; 

Nếu tôi sử dụng công ước này khi tôi có thể tạo cả a và b, tôi nhận được quyền đầu ra và các con trỏ isa dường như khác nhau cho mỗi đối tượng.

Tôi có làm gì sai không? Tôi đã nghĩ nhiều lớp có thể có cùng tên khởi tạo, nhưng có lẽ đó không phải là trường hợp.

Trả lời

5

Vấn đề là phương thức +alloc trả về đối tượng thuộc loại id để trình biên dịch không thể quyết định chữ ký phương thức nào sẽ sử dụng. Bạn có thể buộc ứng dụng của bạn chọn đúng bộ chọn theo một số cách. Một người có thể phân phối lợi tức từ phân bổ, vì vậy:

A* a = [(A*)[A alloc] initWithNum:20.f]; 
B* b = [(B*)[B alloc] initWithNum:10]; 

Hoặc bạn có thể ghi đè phân bổ cho lớp học của mình và trả lại một cái gì đó cụ thể hơn, mặc dù tôi sẽ không tự làm điều này. Vì vậy:

+ (A*)alloc { return [super alloc]; } 

Cuối cùng, và những gì cá nhân tôi sẽ chọn, làm cho selectors mô tả nhiều hơn:

// A.h 
- (id)initWithFloat:(float)theNum; 

// B.h 
- (id)initWithInteger:(int)theNum; 
+1

Bạn cũng có thể thêm tĩnh 'typeWithArgument: 'phương pháp, như' [NSNumber numberWithInt:] 'để phân biệt. – drawnonward

+0

Theo tài liệu, bạn nên đặt 'isa' ivar khi bạn gọi' + [NSObject alloc] '. Vì các công văn Message-Objective-C được giải quyết trong thời gian chạy, không phải là công việc của thời gian chạy, không phải công việc của trình biên dịch, để tìm ra những gì '+ [A alloc]' giải quyết? –

+0

@Nick Forge: Việc triển khai được tự động ràng buộc để không phải là vấn đề (và điều đó đúng ở đây vì NSLog hiển thị A và B như mong đợi). Trường hợp trình biên dịch có liên quan đến việc xây dựng lệnh gọi hàm obj_msgSend. Trong trường hợp này, một bộ chọn sử dụng một phao trong khi bộ chọn khác sử dụng một số nguyên, và trình biên dịch tạo ra các lệnh khác nhau (lưu trữ int trong một thanh ghi nguyên và phao trong thanh ghi fp). Bởi vì điều này, việc thực hiện các phương pháp tìm thấy dữ liệu xấu whne nó trông trong sổ đăng ký dự kiến. –

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