什么时候定义objective-c方法?

Posted

技术标签:

【中文标题】什么时候定义objective-c方法?【英文标题】:When do I define objective-c methods? 【发布时间】:2010-11-04 10:32:45 【问题描述】:

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

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

1234563该文件(好吧,前提是您没有在其他地方使用“extern”声明它)。

现在,在 Objective-C 中,您似乎只需要在头文件中声明选择器以供外部使用,并且您可以在 .m 文件中构建选择器好的,然后在 .m 文件中调用它们。此外,委托方法或继承方法似乎永远不会(重新)定义。

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

【问题讨论】:

【参考方案1】:

对于 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 调用的人都需要自担风险,并且通常会在更改破坏代码时损害他们的利益。 :-)

【讨论】:

+1。感谢您提出我们不应该需要钢板来防止同事弄乱我们的立方体,我们不应该需要语言强制来防止他们弄乱内部数据结构。如果我们需要任何一个,我们就需要更好的同事。编译器警告很重要(连同 -Werror),就像冰箱里食物上的小标签说“这是我的,不要吃”。 ObjC 是一种成人语言。即使你妈妈(编译器)没有强迫你,你也要遵守规则。因此,您不必像在其他语言中那样经常在编译器周围寻找技巧。 我希望我没有错过重点,但我经常想知道是否可以使用这种分层 API 的结构隐藏成员变量,或者是否仍然需要在 MyClass.h 中声明所有内容? @Quinn 非常感谢您宝贵的时间......真的是 SO 上的美丽答案之一 :)【参考方案2】:

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

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

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

个人喜好。如果它是一种公共方法(即外部使用的方法)。在 .h 中声明它并在 .m 中定义。如果您想限制它的可见性,或者至少表明它是私有方法,请在 .m 文件中使用 categories/class extensions。虽然很多示例代码都使用了惰性声明方法。

【讨论】:

【参考方案3】:

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

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

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

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

【讨论】:

澄清:“@private”关键字只能用于变量声明,不能用于方法。可以在一个附加的头文件中声明旨在私有的方法,该头文件包括公共标头并由实现包含(而不是公共标头)。

以上是关于什么时候定义objective-c方法?的主要内容,如果未能解决你的问题,请参考以下文章

52个有效方法 - 了解Objective-C语言的起源

iOS底层学习——KVC

C 函数与 Objective-C 方法?

我啥时候应该在objective-c中释放这些对象?

Object类型转换成自定义类型(向下转型)

Objective-C 使用宏定义来做最基本的代码函数混淆