正确使用Objective C的方法

10 cocoa objective-c

这不是一个风格问题.它更多的是正确使用语言本身.我对编程很新,而且我对Objective-C和Cocoa完全不熟悉,但在阅读了该语言并查看了一些示例代码后,一些使用模式继续弹出,对我来说没有意义.或者说,在我看来,它们似乎并不是最优的.我希望你们都能帮助教育我正确使用其中一些语言结构.

接口与协议

我理解与抽象相关的接口和实现的概念.然而,我在Objective-C示例代码中看到的主导模式如下......

@interface Foo : NSObject
{
  some ivars decls
}
some methods decls
@end
Run Code Online (Sandbox Code Playgroud)

Foo* f = [[Foo alloc] init];
Run Code Online (Sandbox Code Playgroud)

@protocol Foo <NSObject>
  some methods
  maybe some properties
@end

@interface FooProvider : NSObject
  + (FooProvider*) sharedProvider;
  - (id<Foo>) fooWithBlahBlah;
@end
Run Code Online (Sandbox Code Playgroud)

id<Foo> f = [[FooProvider sharedProvider] fooWithBlahBlah];
[f whatever];
Run Code Online (Sandbox Code Playgroud)

@interface Foo : NSObject
{
  some ivars decls
}
some methods decls
@end
Run Code Online (Sandbox Code Playgroud)

Foo* f = [[Foo alloc] init];
Run Code Online (Sandbox Code Playgroud)

@protocol Foo <NSObject>
  some methods
  maybe some properties
@end

@interface FooProvider : NSObject
  + (FooProvider*) sharedProvider;
  - (id<Foo>) fooWithBlahBlah;
@end
Run Code Online (Sandbox Code Playgroud)

这似乎(至少对我来说)是一种更抽象的语言用法,并将客户端与他们不应依赖的实现细节隔离开来.我的问题是我应该努力遵循哪一个.我理解可能存在一种情况比另一种情况更可取的情况,但一般来说,一种情况应该是常态,一种情况是例外吗?

一些指导意见将不胜感激.

谢谢,罗马

gro*_*hog 12

首先,您需要了解您犯了一个经典错误:您已经知道的语言定义了所有语言中使用的术语 - 就好像某个特定语言已经建立了一个规范的命名法.

Java于1990年在Sun内部开始.Objective-C已于1986年发布.因此,如果有的话,Java的接口术语与Objective-C不一致,而不是相反.但是,作为一个术语,接口的历史要长于这些语言中的任何一种.

Objective-C 2.0编程语言参考中概述了Objective-C中 @interface背后的想法:

interface Objective-C类规范的一部分,用于声明其公共接口,包括其超类名称,实例变量和公共方法原型.

实例方法是类方法,如果在接口中声明它们是公共的.如果它们在@implementation中声明它们是私有的.

实现进入@implementation.也许令人困惑的是,Java没有像Objective-C那样的类声明部分的概念.类声明以通用方式声明类接口,没有实现的细节.@implementation具有实际的实现,这是关于如何实现类@interface的细节.

Objective-c与Java不同并没有错,它只是不同.

但是你是对的,协议是你将要找到的objective-c中最接近java接口的模拟.它不是任何东西的超类,也没有任何相关的实现.您提供的协议与Java中的接口一样多.

但是,请注意协议不像Objective-C中的类那样常见.这应该有助于指导你的思考.

  • 那么,您使用Java语言的"接口"这个术语的用户可以看出基于Java的术语和概念的理解,但在Java的概念框架之外并不一定有效.学习语言是一项非常有用的练习 - 学会欣赏知识差异,以便为您使用其他语言提供信息. (2认同)

e.J*_*mes 10

我可以看到你在哪里问候来到命名@interface的关键字,但Objective-C的使用两个关键字@interface@implementation类声明(接口),其定义(实现)之间进行区分.该@interface部分通常放在类头文件中,该@implementation部分放在源文件中.我同意你100%的内部实例变量确实不应该出现在头文件中.我不确定是什么导致了这个决定,但我最好的猜测是它与对象继承有关.从父类继承时:

#import "ParentClass.h"
@interface MyClass : ParentClass
...
Run Code Online (Sandbox Code Playgroud)

您还继承了所有实例变量,除非这些变量在类头中声明,否则编译器很难确定.

@protocol对它的用法也是正确的,因为它本质上定义了一个类必须遵守的接口.协议似乎是Objective-C对多重继承的回答.

根据我对Objective-C的使用经验,不经常使用协议.它们有它们的位置,但是大多数代码使用基本@interface@implementation关键字来定义类,而协议仅在需要一些不完全属于类层次结构的额外功能时使用,但仍需要在多个班级.

如果您正在寻找指导,我会说:

  1. 接受@interface@implementation关键字的命名,即使它与您的期望不相符.在Objective-C中编程时,喝Kool-Aid并按语言设计者的意图查看这些关键字.
  2. 在代码中使用协议时,请使用协议,但不要过度使用协议,以使Objective-C的行为更像另一种语言.它可能有用,但是当他们看到你的代码时,其他人会畏缩,这将使协作变得困难.
  3. 继续问这么好的问题.你提出了一些非常有效的观点!