2011-04-16 28 views
14

Một lớp học có thể kéo dài trong Objective C sử dụng một thể loại như:Mục tiêu-C Tên danh mục có làm gì không?

@interface NSString (CategoryName) 
-(NSString *)myFabulousAddition; // a fabulous additional method 
@end 

///////////////////////////// 
@implementation NSString (CategoryName) 

-(NSString *)myFabulousAddition { 
    // do something fabulous... 

} 
@end 

Trong ví dụ nhỏ này, tôi sẽ có thêm phương pháp myFabulousAddition để NSString. Sau đó tôi có thể gọi nó bằng [anNSString myFabulousAddition] giống như thể nó là một phần của bộ phương pháp NSString. Tuyệt vời và hữu ích.

Trong Apple documents regarding Categories, trạng thái tài liệu:

Không có giới hạn cho số loại mà bạn có thể thêm vào một lớp , nhưng mỗi tên loại phải khác nhau, và mỗi nên kê khai, xác định một nhóm phương pháp khác.

gì nếu bạn có một cái gì đó như thế này:

@interface NSString (CategoryName) 
-(NSString *)myFabulousAddition; // a fabulous additional method 
@end 

@interface NSString (ANOTHERCategoryName) 
-(NSString *)myFabulousAddition; // a DIFFERENT fabulous additional method 
            // BUT with same name as the other category 
@end 


///////////////////////////// 

@implementation NSString (CategoryName) 

-(NSString *)myFabulousAddition { 
    // do something fabulous... 

} 
@end 
@implementation NSString (ANOTHERCategoryName) 

-(NSString *)myFabulousAddition { 
    // do something equally fabulous, but DIFFERENT... 

} 
@end 

Việc thiếu một tên trong ngoặc chỉ ra rằng hình thức là một mở rộng của lớp, như vậy:

@interface MyObject() // No name -- an extension vs category to MyObject 
- (void)setNumber:(NSNumber *)newNumber; 
@end 

Tên danh mục có bất kỳ ý nghĩa nào đối với trình biên dịch hoặc trình liên kết không? Phần tên danh mục của chữ ký phương thức có được hay không là một phần của không gian tên nguyên thủy? Nếu tên danh mục là vô nghĩa, làm thế nào để bạn biết nếu bạn sắp sửa dẫm lên một phương pháp khác và nhận được hành vi không xác định?

Trả lời

6

Cách để tránh dậm về phương pháp là tiền tố tên phương pháp loại của bạn, như thế này:

@interface NSString (MyCompanyCategoryName) 

- (NSString *)MYCO_fabulousAddition; 

@end 

Nếu bạn nhận được một va chạm của tên phương pháp từ loại khác nhau, sau đó một 'chiến thắng' tại thời gian chạy hoàn toàn không xác định.

Tên của danh mục gần như hoàn toàn vô dụng, ngoại trừ việc danh mục không tên (ví dụ: ()) được dành riêng cho tiện ích mở rộng lớp học. Các phương thức từ tiện ích mở rộng lớp được cho là được triển khai trong lớp chính @implementation của lớp học.

+2

Dường như sự bảo vệ duy nhất của tôi là 'SomeUniquePrefixForMyCompanyOrMeThatIsUglyFabulousMethod' chỉ thêm vào hội chứng căng thẳng lặp đi lặp lại trên ngón tay nghèo của tôi ... Cảm ơn! –

+0

Và thực sự thêm tiền tố vào các phương pháp bạn đang thêm với một danh mục cũng được đề xuất bởi Apple ... – Moszi

+1

@ carrot-top sẽ đúng nếu Xcode không cung cấp mã hoàn thành. –

1

Hành vi là (phần lớn) không thể đoán trước - một trong các danh mục sẽ thắng, nhưng bạn không thể biết được danh mục nào. Ngoài ra, tôi nghĩ rằng nó cũng có thể bạn sẽ bắt đầu với một thực hiện và kết thúc với một số khác (nếu thể loại thứ hai được nạp sau lần đầu tiên).

+1

http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocCategories.html%23//apple_ref/doc/uid/TP30001163-CH20-SW1 nói "Khung -phương pháp đã xác định mà bạn cố gắng ghi đè có thể đã được triển khai trong một danh mục và do đó việc triển khai nào được ưu tiên không được xác định. " –

3

Tên danh mục không có ý nghĩa gì đặc biệt, nó chỉ là số nhận dạng. Trừ khi trình liên kết (hoặc trình nạp thời gian chạy) quyết định cung cấp cho bạn một cảnh báo, không có cách nào để nói rằng nhiều danh mục đang định nghĩa cùng một phương thức.

0

tôi tin rằng chúng không có ý nghĩa gì cả. Bạn không thực sự sử dụng chúng trong mã của bạn ... Vì chúng là các loại và ... ngữ nghĩa của một thể loại ... chỉ là để phân loại một cái gì đó, tôi nghĩ rằng điều này là hơi hợp lý ... Tôi sẽ nói rằng họ chỉ chỉ cần thu thập các phương thức ...

Mặt khác câu hỏi của bạn rất hợp lệ ... Bạn KHÔNG BIẾT nếu bạn ghi đè phương thức. Nếu bạn đang ở trong cùng một dự án thì trình biên dịch đưa ra một cảnh báo (hoặc một lỗi? Tôi không nhớ), tuy nhiên nếu bạn đang ghi đè một phương thức từ một thư viện, thì .. bạn đã hết may mắn ...

+0

Sự quan tâm của tôi là không quan trọng hơn phương pháp của thư viện bên thứ ba một cách vô tình. Giả sử tôi thêm một bên thứ ba hoặc mã nguồn mở để thêm 'trim' vào NSString. Tôi cũng có 'trim' trong hộp công cụ của tôi cho NSString. Ai 'cắt' chúng ta sẽ sử dụng? Không xác định không có cảnh báo ... Grrrr. –

+0

Thật không may, Objective-C có một không gian tên duy nhất, buộc các nhà phát triển libs bên thứ ba chơi trò chơi như thêm tiền tố vào danh mục của họ mà họ hy vọng sẽ là (và duy trì) duy nhất. Tôi sử dụng tên viết tắt của tôi với dấu gạch dưới và hy vọng cho điều tốt nhất (như Objective-C nhận được nhiều không gian tên ngay sau đó.) – Rayfleck

+0

Có. không xác định ... tôi cũng không thích hành vi này ... – Moszi

1

Nó chắc chắn hoạt động như một định danh, từ quan điểm của lập trình viên. Trong trình biên dịch của các phương pháp xem thể loại đơn giản được thêm vào như là một phần mở rộng của lớp (từ đó nó được mở rộng), bất kể tên.

Và có, bạn có thể thêm các danh mục của cùng một lớp với cùng số nhận dạng, ngay cả với cùng chức năng. Nhưng bạn chắc chắn không thể ghi đè bất kỳ hàm nào vì các danh mục chỉ là một phần của lớp khi bạn định nghĩa chúng (giống như bạn không thể ghi đè lên một hàm của một lớp từ bên trong lớp đó).

Khi chúng được thêm vào khi chạy, chúng không gây ra bất kỳ lỗi nào và chỉ khi trình biên dịch thời gian chạy chọn chức năng, điều này hoàn toàn không thể đoán trước.

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