2009-06-19 27 views
34

Tôi đang học Objective-C và có nền C/C++.Khi nào tôi xác định các phương pháp target-c?

  • Trong hướng đối tượng C++, bạn luôn cần phải khai báo phương pháp của bạn trước khi bạn xác định (thực hiện) nó, ngay cả khi nó được khai báo trong các tầng lớp phụ huynh.

  • Trong C theo kiểu thủ tục, IIRC, bạn có thể lấy đi chỉ bằng cách định nghĩa một hàm miễn là nó chỉ được gọi từ một cái gì đó khác trong cùng một đơn vị compilational (tức là cùng một tệp). tập tin (tốt, miễn là bạn không khai báo nó ở nơi khác với "extern").

  • Bây giờ, trong mục tiêu-C, có vẻ như bạn chỉ cần khai báo bộ chọn trong tệp tiêu đề nếu chúng được sử dụng bởi thứ gì đó bên ngoài và bạn có thể tạo bộ chọn trong tệp .m của bạn và gọi chúng trong tệp .m. Ngoài ra, có vẻ như các phương thức ủy nhiệm hoặc các phương thức kế thừa không bao giờ được xác định lại.

Tôi có đi đúng hướng không? Khi nào bạn cần định nghĩa một bộ chọn trong Objective-C?

Trả lời

78

Đối với các phương pháp Mục tiêu-C, thực hành chung là đặt các phương thức bạn muốn hiển thị trong phần @interface của tệp tiêu đề để mã khác chỉ có thể bao gồm .h và biết cách tương tác với mã của bạn. Lệnh "lazy declaration" dựa trên lệnh giống như các hàm trong C - bạn không phải khai báo nguyên mẫu phương thức trừ khi bạn có một sự phụ thuộc không thể được giải quyết bằng cách đặt hàng, nhưng bạn có thể thêm các nguyên mẫu phương thức bên trong @implementation nếu cần thiết.

Vì vậy, có, bạn đang đi đúng hướng. Đừng lặp lại nguyên mẫu phương thức cho các phương thức kế thừa - trình biên dịch tìm thấy nó trong tệp tiêu đề của cha mẹ. Các phương thức ủy quyền có thể được định nghĩa là các nguyên mẫu trong một thể loại (được xếp vào một lớp) và được thực hiện như mong muốn, nhưng đại biểu không cần phải cung cấp một nguyên mẫu phương thức, vì nó đã được định nghĩa. (Nó vẫn có thể nếu nó muốn cho rõ ràng, vv)

Vì bạn đang học Objective-C, phần còn lại của câu trả lời này chi tiết hơn nhiều so với bạn đã yêu cầu. Bạn đa được cảnh bao. ;-)


Khi bạn tĩnh gõ một biến (ví dụ MyClass* thay vì id) trình biên dịch sẽ cảnh báo bạn khi bạn cố gắng gọi một phương thức mà một lớp không quảng cáo rằng nó thực hiện, cho dù nó hay không. Nếu bạn tự động gõ biến, trình biên dịch sẽ không ngăn bạn gọi bất cứ điều gì bạn thích, và bạn sẽ chỉ nhận được lỗi thời gian chạy nếu bạn gọi một cái gì đó không tồn tại. Theo như ngôn ngữ có liên quan, bạn có thể gọi bất kỳ phương thức nào mà một lớp thực hiện mà không có lỗi trong thời gian chạy - không có cách nào để hạn chế ai có thể gọi một phương thức.

Cá nhân, tôi nghĩ đây thực sự là một điều tốt. Chúng tôi nhận được như vậy được sử dụng để đóng gói và bảo vệ mã của chúng tôi từ mã khác mà đôi khi chúng tôi đối xử với người gọi như một miscreant devious chứ không phải là một đồng nghiệp đáng tin cậy hoặc khách hàng. Tôi thấy khá dễ chịu khi viết mã với một suy nghĩ về "bạn làm công việc của bạn và tôi làm công việc của tôi", nơi mọi người tôn trọng ranh giới và chăm sóc cho chính họ. Bạn có thể nói rằng "thái độ" của Mục tiêu-C là một trong những niềm tin của cộng đồng, thay vì thực thi nghiêm ngặt. Ví dụ, tôi rất sẵn lòng giúp đỡ bất cứ ai đến bàn làm việc của tôi, nhưng sẽ rất khó chịu nếu ai đó làm rối tung đồ của tôi hoặc di chuyển mọi thứ xung quanh mà không hỏi. Mã được thiết kế tốt không phải là hoang tưởng hoặc sociopathic, nó chỉ cần làm việc tốt với nhau. :-)

Điều đó nói rằng, có nhiều cách tiếp cận để cấu trúc giao diện của bạn, tùy thuộc vào mức độ chi tiết bạn muốn/cần trong việc hiển thị giao diện cho người dùng. Bất kỳ phương pháp nào bạn khai báo trong tiêu đề công khai đều là trò chơi công bằng cho mọi người sử dụng. Ẩn phương pháp khai báo hơi giống như khóa xe hoặc nhà của bạn - nó có thể sẽ không giữ tất cả mọi người, nhưng (1) nó "giữ người trung thực trung thực" bằng cách không hấp dẫn họ với một cái gì đó họ không nên rối tung, và (2) bất cứ ai nào nhận được trong chắc chắn sẽ biết họ không được phép, và không thể thực sự phàn nàn về hậu quả tiêu cực.

Dưới đây là một số quy ước tôi sử dụng để đặt tên tệp và nội dung trong mỗi tệp - bắt đầu từ tệp .m ở dưới cùng, mỗi tệp bao gồm tệp ở trên tệp. (Sử dụng một chuỗi bao gồm nghiêm ngặt sẽ ngăn chặn những thứ như cảnh báo biểu tượng trùng lặp.) Một số các mức này chỉ áp dụng cho các thành phần có thể tái sử dụng lớn hơn, chẳng hạn như khung Cocoa. Điều chỉnh chúng theo nhu cầu của bạn và sử dụng bất kỳ tên nào phù hợp với bạn.

  • MyClass.h - API công cộng (Application Programming Interface)
  • MyClass_Private.h - Công ty nội bộ SPI (Hệ thống Programming Interface)
  • MyClass_Internal.h - Dự án nội bộ IPI (Internal Programming Interface)
  • MyClass.m - Thực hiện, nói chung của tất cả các khai báo API/SPI/IPI
  • MyClass_Foo.m - Triển khai bổ sung, chẳng hạn như đối với các loại

API dành cho mọi người sử dụng và được hỗ trợ công khai (thường là ở Foo.framework/Headers). SPI cho thấy chức năng bổ sung cho khách hàng nội bộ của mã của bạn, nhưng với sự hiểu biết rằng hỗ trợ có thể bị giới hạn và giao diện có thể thay đổi (thường là trong Foo.framework/PrivateHeaders). IPI bao gồm các chi tiết cụ thể về việc triển khai không bao giờ nên được sử dụng bên ngoài dự án và các tiêu đề này không được bao gồm trong khung công tác. Bất kỳ ai chọn sử dụng các cuộc gọi SPI và IPI đều có thể tự chịu rủi ro, và thường gây thiệt hại cho họ khi các thay đổi phá vỡ mã của họ. :-)

+12

+1. Cảm ơn bạn đã nâng cao rằng chúng tôi không nên cần các tấm thép để giữ đồng nghiệp không bị rối tung với các hình khối của chúng tôi và chúng tôi không cần phải thực thi ngôn ngữ để giữ cho chúng không bị rối loạn với cấu trúc dữ liệu nội bộ. Nếu chúng ta cần, chúng ta cần đồng nghiệp tốt hơn. Cảnh báo biên dịch là quan trọng (cùng với -Werror), giống như các nhãn nhỏ trên thực phẩm trong tủ lạnh nói rằng "đây là của tôi, không ăn nó." ObjC là ngôn ngữ dành cho người lớn. Bạn làm theo các quy tắc ngay cả khi mẹ của bạn (trình biên dịch) không ép buộc bạn. Và do đó bạn không cần phải tìm các thủ thuật xung quanh trình biên dịch như bạn thường làm như vậy bằng các ngôn ngữ khác. –

+1

+1 Câu trả lời hay! :) –

+0

Tôi hy vọng tôi không bị thiếu điểm, nhưng tôi thường tự hỏi liệu có thể ẩn các biến thành viên bằng cấu trúc của các lớp của lớp này, hay mọi thứ vẫn cần được khai báo trong MyClass.h? – Akusete

6

Khai báo các phương thức trong tệp tiêu đề sẽ chỉ dừng cảnh báo trình biên dịch. Mục tiêu-C là một ngôn ngữ động, vì vậy bạn có thể gọi một phương thức (gửi một tin nhắn) đến một đối tượng cho dù phương thức đó được khai báo bên ngoài hay không.

Ngoài ra, nếu bạn xác định phương thức trong tệp .m phía trên bất kỳ mã nào gọi nó (khai báo lười) thì sẽ không tạo ra bất kỳ cảnh báo nào. Tuy nhiên, điều tương tự cũng được áp dụng, bạn có thể gửi một tin nhắn đến một đối tượng mà không cần nó được khai báo.

Tất nhiên - điều này có nghĩa là không có phương pháp riêng trong Mục tiêu-C. Bất kỳ phương thức nào mà một lớp thực hiện có thể được gọi.

Tùy chọn cá nhân. Nếu đó là phương thức công khai (nghĩa là phương thức được sử dụng bên ngoài). khai báo nó trong .h và xác định trong .m. Nếu bạn muốn giới hạn khả năng hiển thị của nó hoặc ít nhất cho biết đó là phương pháp riêng tư, hãy sử dụng categories/class extensions trong tệp .m. Mặc dù rất nhiều mã ví dụ sử dụng phương thức khai báo lười biếng.

3

Objective-C coi các chức năng là "tin nhắn" và như vậy, bạn có thể gửi "thông điệp" tới bất kỳ đối tượng nào - ngay cả đối tượng không rõ ràng trong giao diện của nó. Kết quả là, không có những thứ như thành viên tư nhân trong Obj-C.

Điều này có thể rất mạnh mẽ, nhưng là một nguồn gây nhầm lẫn cho các lập trình viên mới của Obj-C - đặc biệt là những người đến từ C++, Java hoặc C#. Dưới đây là những nguyên tắc cơ bản của ngón tay cái:

  • Bạn nên xác định tất cả các phương pháp nào trong @ interface của bạn để người tiêu dùng biết những thông điệp mà bạn mong đợi để xử lý.
  • Bạn nên định nghĩa các phương thức @private trong @interface của mình để tránh các thông điệp trình biên dịch và tránh phải đặt hàng các phương thức trong @implementation.
  • Bạn nên sử dụng các giao thức khi triển khai một quy ước phương thức cụ thể cho lớp học của mình.

Phần lớn là tùy chọn cá nhân, tuy nhiên nó giúp tránh cảnh báo trình biên dịch gây phiền nhiễu và giữ mã của bạn được sắp xếp. và dễ hiểu.

+1

Làm rõ: Từ khóa "@private" chỉ có thể được sử dụng cho các khai báo biến, không phải phương thức. Các phương thức nhằm mục đích riêng tư có thể được khai báo trong một tệp tiêu đề bổ sung bao gồm tiêu đề công khai và được bao gồm bởi việc triển khai (thay vì tiêu đề công khai). –

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