2009-06-27 20 views

Trả lời

39

Hai cú pháp phục vụ các mục đích khác nhau.

Một loại tên - @ interface Foo (FooCategory) - thường được sử dụng để:

(1) mở rộng một lớp hiện có bằng cách thêm chức năng. Ví dụ: NSAttributedString trong Foundation được mở rộng bởi một thể loại trong AppKit thêm API định dạng văn bản giống như RTK cụ thể của AppKit.

(2) khai báo một tập hợp các phương pháp có thể hoặc không thể được thực hiện bởi đại biểu. Ví dụ: Các lớp khác nhau khai báo - nhưng không triển khai - @interface NSObject (SetODelegateMethods).

Biểu mẫu (2) đã mất ưu tiên vì @protocol đã được mở rộng để hỗ trợ các phương pháp @optional trong Mục tiêu-C 2.0.

Mở rộng lớp - @interface Foo() - được thiết kế để cho phép bạn khai báo thêm API riêng - SPI hoặc Giao diện lập trình hệ thống - được sử dụng để triển khai nội dung lớp. Điều này thường xuất hiện ở đầu tệp .m. Bất kỳ phương thức/thuộc tính nào được khai báo trong phần mở rộng lớp phải được thực hiện trong @implementation, giống như các phương thức/thuộc tính được tìm thấy trong công khai @interface.

Tiện ích mở rộng lớp học cũng có thể được sử dụng để redeclare một @ readperly chỉ đọc là ghi đè trước khi @ synthesize'ing người truy cập.

Ví dụ:

foo.h

@interface Foo:NSObject 
@property(readonly, copy) NSString *bar; 
-(void) publicSaucing; 
@end 

Foo.m

@interface Foo() 
@property(readwrite, copy) NSString *bar; 
- (void) superSecretInternalSaucing; 
@end 

@implementation Foo 
@synthesize bar; 
.... must implement the two methods or compiler will warn .... 
@end 
+0

Không phải thanh @synthesize; dòng có nghĩa là trình biên dịch sẽ tạo ra hai phương pháp (getter và setter) cho thanh? – Elliot

+2

Có, nhưng chỉ getter được khai báo trong tiêu đề công khai, setter được khai báo riêng để sử dụng bên trong chính lớp đó. Đây không phải là C++, nếu bạn muốn quan sát thời gian chạy, bạn có thể tìm ra setter đang ở đó và gọi nó ở đâu mà bạn muốn, nhưng trừ khi bạn làm rõ điều đó, bạn sẽ nhận được cảnh báo biên dịch nếu bạn tình cờ cố gắng thiết lập thuộc tính. –

+0

@Louis là chính xác. Thuộc tính thứ hai ghi đè rằng "readonly" trong thuộc tính tệp .h bằng cách chỉ định "readwrite", vì vậy đó là những gì trình biên dịch thực sự làm. Tuy nhiên, chỉ có trình hiển thị cho những người bao gồm tệp tiêu đề, vì khi họ nhập tệp, họ sẽ chỉ thấy phiên bản "chỉ đọc" của thuộc tính. –

2

Vâng,

có những khác biệt sau.

1) Sử dụng danh mục ẩn danh yêu cầu triển khai các phương thức của nó trong khối @implementation chính cho lớp tương ứng; danh mục ẩn danh cho phép bạn khai báo API bắt buộc bổ sung cho một lớp ở các vị trí khác ngoài lớp chính @interface block

2) Khi sử dụng MyClass (riêng tư), điều sau phải được tính đến: cặp tên/đối tượng được đặt tên phải là duy nhất. Nếu bạn khai báo một danh mục riêng trên lớp của riêng mình, thì không có vấn đề gì. Tuy nhiên, mọi thứ khác nhau trên các lớp hiện có. Ví dụ, chỉ có một thể loại NSString (Private) có thể tồn tại trong một không gian tên Objective-C đã cho. Điều này có thể dẫn đến các vấn đề vì không gian tên Objective-C được chia sẻ giữa mã chương trình và tất cả các thư viện, khung công tác và trình cắm. Điều này đặc biệt quan trọng đối với các lập trình viên Objective-C viết screensaver, các khay tùy chọn và các trình cắm thêm khác bởi vì mã của họ sẽ được đưa vào mã ứng dụng hoặc khung công tác mà họ không kiểm soát.

+0

Bạn có chắc chắn đó là trường hợp đó loại phải được đặt tên duy nhất? Đó là sự hiểu biết của tôi rằng miễn là các bộ chọn là duy nhất, sẽ không có xung đột. Là thời gian chạy thậm chí nhận thức được các loại? (tham chiếu thời gian chạy không đề cập đến chúng) – rpetrich

+0

Đó không phải là danh mục phải được đặt tên duy nhất: đó là đối tượng/danh mục cặp phải.Hãy thử tự biên dịch hai loại NSString (Riêng tư) khác nhau, thậm chí sử dụng các phương thức khác nhau trong một dự án của bạn và xem liệu nó có hoạt động hay không. –

+0

Hmm ... có vẻ như trình biên dịch/trình liên kết không cho phép các danh mục trùng lặp trên một lớp, nhưng thời gian chạy không. Bạn có thể định nghĩa các danh mục NSDictionary (NSDictionary) hoặc NSError (NSErrorPrivate) với phương thức + tải và trình biên dịch, trình liên kết và thời gian chạy sẽ hoạt động như mong đợi (mặc dù Foundation.framework thực hiện cả hai loại này trong nội bộ). Nếu bạn thực hiện một thể loại được đặt tên trong một tiêu đề như NSString (NSStringExtensionMethods), trình biên dịch sẽ phát ra các cảnh báo, nhưng trình liên kết và thời gian chạy vẫn hoạt động như mong đợi. Không ai trong số này thực sự hữu ích trong thế giới thực. – rpetrich

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