2011-12-18 25 views
6

Giả sử rằng:Nếu phương thức Protocol được đánh dấu @required, khi không được triển khai, tại sao trình biên dịch đưa ra cảnh báo chứ không phải lỗi?

  • New Nghị định thư được khai báo
  • Phương pháp trong giao thức này được đánh dấu @required
  • lớp phù hợp với Nghị định thư
  • Lớp làm không thực hiện các phương pháp nêu trong Nghị định thư

Tại thời gian biên dịch, thông tin về phương pháp này được biết: nghĩa là nó được yêu cầu và rằng lớp này và bất kỳ lớp nào khác mà lớp này có thể mở rộng không thực hiện nó.

Tại sao trong trường hợp này trình biên dịch đưa ra cảnh báo chứ không phải lỗi?

Trả lời

6

Lỗi chỉ được phát hành khi trình biên dịch không thể tiếp tục vì đã xảy ra lỗi nghiêm trọng.

Khi gọi một phương thức trong Mục tiêu-C, tra cứu phương pháp được thực hiện trong suốt thời gian chạy chứ không phải trong quá trình biên dịch, mà C++ thực hiện. Trong Objective-C, một "message" được gửi đến đối tượng, giống như obj.executeCommand("Hey, can you execute function <name> for me?"). Trong C++, đối tượng sẽ được gọi trực tiếp, theo cách như obj.<name>(). Trong trường hợp của Objective-C, phương thức executeCommand() được gọi, tồn tại. Trong trường hợp của C++, hàm này được gọi nhưng nó không tồn tại. Đây là những phương thức được liên kết ở cấp trình biên dịch, có nghĩa là cả hai đều trở thành địa chỉ bộ nhớ thay vì tên. executeCommand trở thành 0x12345678 nhưng vẫn sử dụng cùng một thông báo ("execute function <name>").

Điều này có thể rất khó hiểu, nhưng nó liên quan đến cách thức các phương pháp được triển khai bằng các ngôn ngữ khác nhau.

0

Tôi không biết câu trả lời thực sự nhưng đây là trường hợp sử dụng có thể chống lại nó.

Điều gì xảy ra nếu bạn triển khai tất cả các phương thức giao thức trong một danh mục ???

Tuyên bố giao diện chính thông qua giao thức tuy nhiên việc triển khai phương thức giao thức nằm trong danh mục. Đây là mã hợp lệ nhưng sẽ hiển thị lỗi biên dịch nếu trình biên dịch nghiêm ngặt !!

2

Nếu bạn cảm thấy mạnh mẽ về điều đó, tại sao không bật -Werror?

0

Mục tiêu-C là ngôn ngữ động. Ý tưởng về việc triển khai thực hiện là gì, khác với ngôn ngữ tĩnh.
Đối với hầu hết các phần, đó là mã mà hầu hết chúng ta thực hiện bên trong @implementation ... @end block.
Nhưng nếu không tìm thấy phương pháp thì sao? Sau đó, một đối tượng có cơ hội đối phó với nó một cách năng động.

Hãy tưởng tượng bạn có một giao diện cho một cầu thủ hiệu ứng âm thanh:

@protocol FX 
- (void)playBeep; 
- (void)playSiren; 
- (void)playHonk; 
@end 

An thực hiện có thể có các tập tin Beep.mp3, Siren.mp3, Honk.mp3 để chơi, nhưng thay vì thực hiện mỗi phương pháp, nó có thể ghi đè lên -forwardInvocation: và phân tích chuỗi selector, một cái gì đó giống như giả này:

NSString *selName = NSStringFromSelector([invocation selector]); 
if ([selName startsWith:@"play"]) { 
    NSString filename = fileNameFromSelector(selName); 
    [self playSoundFileNamed:filename]; 
} 

Điều này có vẻ giả tạo, nhưng một khi bạn bắt đầu sử dụng các tính năng động của ngôn ngữ, bạn sẽ bắt đầu tìm kiếm ngày càng nhiều nơi có ý nghĩa. Và ý tôi là, nỗ lực này có giúp ích lâu dài không?

Trong trường hợp trên, chỉ cần thêm tên phương thức -sound * vào giao diện và thả vào tệp âm thanh được đặt tên phù hợp. Nó chỉ hoạt động.

Ví dụ khác từ thử nghiệm cá nhân: cách đối phó với các thực thể Dữ liệu cốt lõi theo cách tự nhiên hơn. Tôi muốn làm điều này: NSArray * people = [Người tìm thấyTất cảTên người dùngLike: @ "B%"]; thay vì mucking về với các vị từ, tìm nạp các yêu cầu, vv
Nhưng tôi không muốn xác định mọi hoán vị của phương thức trong mã.

Nếu tôi muốn xây dựng trình tạo XML thì sao? Tôi sẽ xem xét một cách tiếp cận năng động. Nó đã phục vụ tốt Groovy Builders (xem Groovy/Grails cho các ví dụ).

Một ví dụ cuối cùng: Tôi có một hệ thống đặc điểm nơi tôi có thể xác định hành vi theo dạng nhóm phương pháp và có đối tượng của tôi đồng hóa hành vi này. Vì vậy, trong khi trình biên dịch không thấy một thực hiện cho giao diện đối tượng của tôi phù hợp, việc thực hiện được tiêm vào nó từ một lớp đặc điểm, sử dụng thời gian chạy Objective-C. Tại sao tôi phải làm điều này? Tôi tìm thấy nhiều phương pháp đại biểu là tấm nồi hơi, nhưng đồng thời, một lớp cơ sở duy nhất cho mỗi tình huống không đủ linh hoạt. Thay vì cắt và dán từ các mẫu mã, biên dịch và chạy mẫu của tôi :) và mọi thay đổi được phản ánh trên tất cả các dự án sử dụng đặc điểm này.

Để thực sự hiểu tại sao tất cả những điều này có sẵn cho bạn, bạn nên chơi đùa với môi trường Smalltalk (tìm kiếm Pharo hoặc Squeak). Đây là nơi Objective-C có nguồn gốc của nó.

Và cuối cùng, để ngăn chặn những cảnh báo này:

#pragma clang diagnostic push 
#pragma clang diagnostic ignored "-Wprotocol" 

@implementation ... @end 

#pragma clang diagnostic pop 
0

Bởi vì có những lúc có là không có thật "bắt buộc" phương pháp trong một giao thức được thiết kế kém. Chúng phải là tùy chọn nhưng ai đó khăng khăng rằng chúng là "bắt buộc". Do đó làm cho vấn đề thời gian chạy này hơn là một lỗi biên dịch là rất rất khôn ngoan.

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