2011-11-06 26 views
7

Trong Objective C, phương pháp giao thức có thể được buộc hay tùy chọn:giao thức C Mục tiêu đòi hỏi phải thực hiện ít nhất một trong một tập hợp các phương pháp

@protocol AProtocol 

@required 
-(void) aRequiredMethod; 

@optional 
-(void) anOptionalMethod; 

@end 

Có một cách thanh lịch để nói rằng đối tượng phù hợp với giao thức đã để đáp ứng ít nhất một trong một tập hợp các phương pháp, giấc mơ của tôi sẽ là một cái gì đó giống như

@protocol AProtocol 

@anyof 
-(void) onePossibleMethod; 
-(void) anotherPossibleMethod; 

@optional 
-(void) anOptionalMethod; 

@end 

EDIT:

Sinh mệnh này (như xa như tôi biết), không thể, wou ld có một cách để tăng cảnh báo thời gian biên dịch nếu một lớp được khai báo là phù hợp với một giao thức đã cho được thực hiện hoàn toàn bằng các phương thức tùy chọn

@protocol AProtocol 

@optional 
-(void) onePossibleMethod; 
-(void) anotherPossibleMethod; 

@end 

không thực hiện được ít nhất một trong số chúng.

+0

lại: 'CHỈNH SỬA' không phải là tôi đã thấy. Nếu bạn thực sự muốn tự động hóa điều này, bạn có thể sử dụng thời gian chạy objc. – justin

Trả lời

3

Có không phải là một cách tuyệt vời để thể hiện điều này trong Objective-C. Nếu bạn phải làm điều này, IMO cách thành ngữ nhất và ít mã nhất là gì đó dọc theo các dòng sau:

@protocol AProtocol 

@required 
- (SEL)methodToUse; // returns one of "onePossibleMethod" or "anotherPossibleMethod" 

@optional 
-(void) onePossibleMethod; 
-(void) anotherPossibleMethod; 
-(void) anOptionalMethod; 

@en 
+0

Tôi đồng ý không có cách nào tuyệt vời, tuy nhiên tôi thích giải pháp của bạn ở chỗ nó "chính thức" (tức là khác với bình luận/tài liệu) cho các nhà phát triển không quen với mã mặc dù ba phương pháp là tùy chọn, bạn mong đợi một trong chúng được thực hiện. – jbat100

0

Bạn có thể có thuộc tính ủy nhiệm động chỉ cho phép ủy nhiệm được gán cho các lớp thực hiện một phương thức hoặc phương thức khác — nhưng đó là thời gian chạy và không phải lúc biên dịch. Bạn cũng có thể tạo tập lệnh bash để kiểm tra xem tập lệnh đó hay cái kia đã được triển khai và thời gian biên dịch.

3

Vâng, bạn đang làm việc với ObjC, vì vậy bạn sẽ cần phải thực hiện một số sự kiềm chế bản thân:

@protocol MONAbstractDataProvider 
@optional 
- (void)anOptionalMethod; 
@end 

@protocol MONDataProviderA <MONAbstractProvider> 
@required 
- (void)onePossibleMethod; 
@end 

@protocol MONDataProviderB <MONAbstractProvider> 
@required 
- (void)anotherPossibleMethod; 
@end 

Trong trường hợp đó, bạn sẽ phải làm một bài kiểm tra confromsToProtocol: tại callsite, chứ không phải là kiểm tra respondsToSelector: cho onePossibleMethodanotherPossibleMethod. Sau đó, bạn vượt qua MONAbstractDataProvider xung quanh. Điều đó có thể giới thiệu một số loại an toàn, miễn là bạn nhớ các quy tắc, nhưng nó thực sự chỉ tốt hơn một chút so với cách tiếp cận thông thường.

Vì vậy, các mặt hàng khác sẽ trông như thế này:

- (void)update:(NSObject<MONAbstractDataProvider>*)provider 
{ 
    if ([provider conformsToProtocol:@protocol(MONDataProviderA)]) { 
     [(NSObject<MONDataProviderA>*)protocol onePossibleMethod]; 
    } 
    else if ([provider conformsToProtocol:@protocol(MONDataProviderB)]) { 
     [(NSObject<MONDataProviderB>*)provider anotherPossibleMethod]; 
    } 
    else { 
     assert(0 && "rule broken"); 
    } 
} 

Điều đó tất nhiên giả định cho khách hàng biết về tất cả các dẫn xuất.

Bạn thay vì có thể thích cách tiếp cận ít đơn giản hơn nếu họ đều void:

@protocol MONAbstractDataProvider 
@required 
- (void)performPossibleMethod; 
@optional 
- (void)anOptionalMethod; 
@end 
+0

cảm ơn câu trả lời chi tiết của bạn, đây sẽ là một cách để thực hiện kiểm tra tại thời gian chạy. Lý tưởng nhất là những gì tôi muốn là một số loại kiểm tra thời gian biên dịch mà sẽ nâng cao một cảnh báo (tôi đã chỉnh sửa các câu hỏi một chút). – jbat100

+0

@ jbat100 hmm - tôi không đưa ra chi tiết về cách tiếp cận rất rõ ràng. việc kiểm tra thời gian biên dịch được nhập vì 'MONAbstractDataProvider' chỉ được chấp nhận * gián tiếp *. các lớp chỉ nên áp dụng 'MONDataProviderA' hoặc' MONDataProviderB', không bao giờ là 'MONAbstractDataProvider' trực tiếp. – justin

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