34

我正在学习 Objective-C,并且有 C/C++ 背景。

  • 在面向对象的 C++ 中,您总是需要在定义(实现)方法之前声明您的方法,即使它是在父类中声明的。

  • 在过程风格的 C、IIRC 中,您可以只定义一个函数,只要它仅从稍后出现在文件中的同一编译单元(即同一文件)中的其他东西调用(好吧,提供您不会在其他地方用“extern”声明它)。

  • 现在,在 Objective-C 中,您似乎只需要在头文件中声明选择器(如果它们将被外部使用),并且您可以在 .m 文件中很好地构建选择器,并在其中调用它们.m 文件。此外,似乎从未(重新)定义委托方法或继承方法。

我在正确的轨道上吗?什么时候需要在 Objective-C 中定义选择器?

4

3 回答 3

78

对于 Objective-C 方法,一般做法是将您希望公开的方法放在@interface头文件的部分中,以便其他代码只能包含 .h 并知道如何与您的代码交互。基于顺序的“惰性声明”就像 C 中的函数一样工作——您不必声明方法原型,除非您有无法通过排序解决的依赖项,但@implementation如果需要,您可以在其中添加方法原型。

所以是的,你在正确的轨道上。不要为继承的方法重复方法原型——编译器会在父类的头文件中找到它。委托方法可以定义为类别中的原型(附加到类上)并根据需要实现,但委托不需要提供方法原型,因为它已经定义。(为了清楚起见,它仍然可以,等等。)

由于您只是在学习 Objective-C,因此此答案的其余部分比您要求的要详细得多。你被警告了。;-)


当您静态键入一个变量(例如MyClass*,而不是id)时,当您尝试调用一个类没有宣传它实现的方法时,无论它是否实现,编译器都会警告您。如果您动态键入变量,编译器不会阻止您调用您喜欢的任何内容,并且只有在调用不存在的内容时才会出现运行时错误。就语言而言,您可以在运行时调用类实现的任何方法而不会出错——没有办法限制谁可以调用方法。

就个人而言,我认为这实际上是一件好事。我们非常习惯于封装和保护我们的代码免受其他代码的影响,以至于我们有时将调用者视为狡猾的恶棍,而不是值得信赖的同事或客户。我发现以“你做你的工作,我做我的工作”的心态来编码是非常愉快的,每个人都尊重界限并照顾自己的事情。你可能会说,Objective-C 的“态度”是一种社区信任,而不是严格执行。例如,我很乐意帮助任何来到我办公桌前的人,但如果有人在没有询问的情况下弄乱我的东西或移动东西,我会非常生气。精心设计的代码不一定是偏执或反社会的,它只需要很好地协同工作。:-)

也就是说,有很多方法可以构建界面,具体取决于您在向用户公开界面时想要/需要的粒度级别。您在公共标头中声明的任何方法本质上都是公平的游戏,任何人都可以使用。隐藏方法声明有点像锁住你的车或房子——它可能不会让每个人都被拒之门外,但是(1)它“让诚实的人保持诚实”,不会用他们不应该搞砸的东西来诱惑他们,以及(2 )任何进入的人肯定会知道他们应该这样做,并且不能真正抱怨负面后果。

以下是我用于文件命名的一些约定,以及每个文件中的内容——从底部的 .m 文件开始,每个文件都包含它上面的文件。(使用严格的包含链将防止出现重复符号警告等情况。)其中一些级别仅适用于较大的可重用组件,例如 Cocoa 框架。根据您的需要调整它们,并使用适合您的任何名称。

  • MyClass.h— 公共 API(应用程序编程接口)
  • MyClass_Private.h— 公司内部 SPI(系统编程接口)
  • MyClass_Internal.h— 项目内部 IPI(内部编程接口)
  • MyClass.m— 实现,通常是所有 API/SPI/IPI 声明
  • MyClass_Foo.m— 附加实现,例如类别

API 是供大家使用的,并且是公开支持的(通常在 中Foo.framework/Headers)。SPI 为您的代码的内部客户端公开了额外的功能,但要理解支持可能会受到限制,并且接口可能会发生变化(通常在 中Foo.framework/PrivateHeaders)。IPI 由特定于实现的细节组成,这些细节绝不应该在项目本身之外使用,并且这些标头根本不包含在框架中。任何选择使用 SPI 和 IPI 调用的人都需要自担风险,并且通常会在更改破坏代码时损害他们的利益。:-)

于 2009-06-19T22:32:04.620 回答
6

在头文件中声明方法只会停止编译器警告。Objective-C 是一种动态语言,因此无论该方法是否在外部声明,您都可以向对象调用方法(发送消息)。

此外,如果您在调用它的任何代码(惰性声明)上方的 .m 文件中定义方法,则不会生成任何警告。然而,同样的事情也适用,您可以在不声明对象的情况下向对象发送消息。

当然——这意味着在 Objective-C 中没有私有方法。可以调用类实现的任何方法。

个人喜好。如果它是一种公共方法(即外部使用的方法)。在 .h 中声明它并在 .m 中定义。如果您想限制它的可见性,或者至少表明它是私有方法,请在 .m 文件中使用类别/类扩展名。尽管许多示例代码使用惰性声明方法。

于 2009-06-19T21:31:36.723 回答
3

Objective-C 将函数视为“消息”,因此,您可以向任何对象发送“消息”——即使是在其接口中没有明确声明它可以接受的对象。因此,在 Obj-C 中没有私有成员之类的东西。

这可能非常强大,但对于新的 Obj-C 程序员来说是一个混乱的根源——尤其是那些来自 C++、Java 或 C# 的程序员。以下是基本的经验法则:

  • 您应该在 @interface 中定义所有公共方法,以便消费者知道您希望处理哪些消息。
  • 您应该在@interface 中定义@private 方法以避免编译器消息并避免必须在@implementation 中对方法进行排序。
  • 在为您的类实现特定的方法约定时,您应该使用协议。

这在很大程度上是个人喜好,但它有助于避免烦人的编译器警告并保持您的代码井井有条。并且易于理解。

于 2009-06-19T21:36:07.930 回答