2009-04-09 41 views
69

Nếu tôi muốn mở rộng một lớp như AVAudioPlayer, cách tốt nhất để thêm một phương thức khác vào AVAudioPlayerDelegate là gì? Tôi có tạo danh mục cho nó không, tôi có mở rộng nó không? Nếu tôi mở rộng nó làm tôi sau đó cũng phải chắc chắn để ghi đè lên các đại biểu thực tế getter/setter? Làm thế nào tôi có thể mở rộng giao thức? Sau đây mang lại cho tôi lỗiLàm thế nào để mở rộng các giao thức/đại biểu trong Mục tiêu-C



@protocol AudioTrackDelegate : AVAudioPlayerDelegate { 
    - (void)foo; 
} 
@end 

@interface AudioTrack : AVAudioPlayer { 
} 
@end 

Trả lời

125

Cú pháp để tạo một giao thức mà thực hiện giao thức khác là như vậy:

@protocol NewProtocol <OldProtocol> 
- (void)foo; 
@end 

Nếu bạn muốn gọi một phương pháp trong NewProtocol trên một con trỏ gõ như OldProtocol bạn có thể hoặc gọi respondsToSelector:

if ([object respondsToSelector:@selector(foo)]) 
    [(id)object foo]; 

Hoặc xác định phương pháp còn sơ khai như một phạm trù trên NSObject:

@interface NSObject (NewProtocol) 
- (void)foo; 
@end 
@implementation NSObject (NewProtocol) 
- (void)foo 
{ 
} 
@end 
+0

Nếu tôi tạo giao thức triển khai giao thức khác ... Tôi có cần làm gì khác để đảm bảo phương pháp 'OldProtocol' bị sa thải hay không ?bởi vì đối với tôi, tôi đang nhận được các giao thức mới bắn nhưng tất cả những cái hiện có không còn nữa – dizy

+10

Một giao thức không có phương thức, nó có định nghĩa phương thức; nghĩa là, nó mô tả tên, đối số và kiểu trả về mà một lớp phải được coi là "tuân thủ" với giao thức đã nói. Theo nhận xét/câu hỏi của bạn Tôi cá rằng bạn quên gọi [super setDelegate: value] trong -setDelegate: – rpetrich

+0

bằng cách sử dụng phương pháp này, bạn không hiển thị các phương thức giao thức mới, hãy xem trả lời của tôi một cách rõ ràng nhất – Kappe

11

Nhớ giao thức không thêm mã vào ứng dụng đã biên dịch - nó chỉ thực thi thực tế là lớp của bạn phải triển khai các phương thức được coi là "tuân thủ" giao thức. Một sử dụng tốt điều này sẽ tạo ra một nhóm các lớp học với tất cả các cách tương tự của hoạt động: <printable> hoặc <serialized>, vv Vì vậy, bạn có thể tạo một giao thức <plays> ví dụ:

@protocol plays 
    - (void) play; 
    - (NSString *) type; 
@end 

Và sau đó một lớp học mà phù hợp đến <plays> PHẢI thực hiện các phương pháp playtype. Nếu không, trình biên dịch sẽ đưa ra cảnh báo nhưng vẫn biên dịch lớp. Trong mã của bạn, bạn kiểm tra xem đối tượng có tuân theo giao thức với mã sau không:

if ([obj conformsTo: @protocol(plays)]) { 
    [obj play]; 
} 

Danh mục thực sự thêm phương thức mới động vào lớp học của bạn. Các phương thức này có thể truy cập toàn cục vào thời gian chạy dưới dạng bộ chọn và có thể được gọi theo tên như trong @selector(foo)[object foo:bar];

Mục đích của danh mục là thêm mã đặc biệt mới vào lớp ngay cả khi bạn không có mã nguồn cho lớp đó. Có thể có những vấn đề bảo mật và bạn có thể tạo ra rò rỉ bộ nhớ trong lớp học, vv

Trong trường hợp của bạn có thể, trong một tệp riêng AVAudioPlayerDelegate_TrackOps.m

#import "AVAudioPlayerDelegate.h" 
@implementation AVAudioPlayerDelegate (TrackOps) 

- (NSObject *) foo { 
    // do foo stuff; 
    return bar; 
} 

@end 

Đưa nó như là một chủng loại NSObject làm cho tất cả các lớp học đáp ứng với foo . Foo cũng có thể là phương pháp độc lập Objc_perform_selector(@selector(foo)).

Dòng dưới cùng: sử dụng danh mục để thêm phương thức nhanh vào lớp, giao thức thực thi triển khai phương pháp và lớp con để chuyên lớp hiện có (những thứ như thêm biến thành viên hoặc chức năng chính mới). Danh mục cũng có thể được sử dụng để ghi đè lên một hoặc hai phương thức khi một lớp con không cần thiết và muốn, nhưng thường là nếu bạn muốn thêm chức năng vào một lớp bạn tạo một lớp con. Để biết thêm ví dụ, ý tưởng, thông tin chung khác về chủ đề này, luôn có Apple introduction to Objective-C

+0

Bạn có thể vui lòng giải thích cách thêm danh mục vào giao thức không? Tôi nghĩ rằng đôi khi sai với cú pháp của những gì bạn đã viết. cảm ơn – dizy

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