我正在学习Objective-C,并且拥有C / C ++背景。
在面向对象的C ++中,总是需要在定义(实现)它之前声明方法,即使它是在父类中声明的。
在程序风格的C,IIRC中,只要在同一个编译单元(即同一个文件)中的其他内容中调用它,就可以轻松定义一个函数。文件(好吧,如果你没有在其他地方用“extern”声明它)。
现在,在Objective-C中,您似乎只需要在头文件中声明选择器,如果它们将被外部使用,并且您可以在.m文件中组成选择器很好,并在.m文件中调用它们。此外,似乎永远不会(重新)定义委托方法或继承方法。
我是否在正确的轨道上?什么时候需要在Objective-C中定义一个选择器?
答案 0 :(得分: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呼叫的人都要自行承担风险,并且在更改破坏代码时通常会造成损害。 : - )
答案 1 :(得分:6)
声明头文件中的方法只会停止编译器警告。 Objective-C是一种动态语言,因此您可以调用方法(发送消息)到对象,无论该方法是否在外部声明。
此外,如果您在.m文件中定义一个方法,而不是任何调用它的代码(延迟声明),那么这将不会生成任何警告。但是同样适用,您可以在不声明对象的情况下向对象发送消息。
当然 - 这意味着Objective-C中没有私有方法。可以调用类实现的任何方法。
个人偏好。如果它是一种公共方法(即外部使用的方法)。在.h中声明它并在.m中定义。如果要限制其可见性,或者至少表明它是私有方法,请在.m文件中使用categories/class extensions。虽然许多示例代码使用延迟声明方法。
答案 2 :(得分:3)
Objective-C将函数视为“消息”,因此,您可以向任何对象发送“消息” - 即使是在其接口中未明确声明它可以接受的对象。因此,在Obj-C中没有私人成员这样的东西。
这可能非常强大,但却是新Obj-C程序员混淆的根源 - 特别是那些来自C ++,Java或C#的程序员。以下是基本的经验法则:
这很大程度上是个人偏好,但它有助于避免恼人的编译器警告并保持您的代码有条理。并且易于理解。