Objective-C类扩展

Jea*_*non 34 objective-c class-extensions

作为一个相当新的Objective-c程序员(具有4年的Java经验),我似乎很难理解何时使用类扩展.根据我的理解(如果我错了请纠正我),类别和扩展之间的主要区别在于扩展期望您在主实现中实现方法,而对于类别,它可以在另一个实现中.似乎人们主要使用扩展主要用于私有方法.

这是我的第一个问题.使用类扩展来声明私有方法,而不是完全声明它(在两种情况下似乎都在运行中编译)之间的区别是什么?(例1 vs 2)

例1

@interface Class()
-(void) bar;
@end

@implementation Class
-(void) foo {
    [self bar];
}

-(void) bar {
    NSLog(@"bar");
}
@end
Run Code Online (Sandbox Code Playgroud)

例2

@implementation Class
-(void) foo {
    [self bar];
}

-(void) bar {
    NSLog(@"bar");
}
@end
Run Code Online (Sandbox Code Playgroud)

第二个问题:在扩展中声明ivars并在实现中直接声明它之间有什么区别?(例3与4)

例3

@interface Class() {
    NSArray *mySortedArray;
}
@end

@implementation Class
@end
Run Code Online (Sandbox Code Playgroud)

例4

@implementation Class
NSArray *mySortedArray;
@end
Run Code Online (Sandbox Code Playgroud)

我有关于编码约定的最后一个问题:我应该何时在变量名称前放置下划线(_)?

谢谢

WDU*_*DUK 28

类扩展中的方法

以前从未出现过您不需要声明私有方法的情况.直到最近,您需要在某处声明您的私有方法,并且大多数人选择了类扩展来执行此操作.从Xcode 4.4(我相信),编译器足够聪明,可以确定哪些方法在该实现中是私有的,从而无需在其他地方声明它们.

类扩展中的变量

至于例3和4,要小心.在类扩展中,变量是该类的实例变量(示例3).示例4声明了一个全局变量(由于它遵循来自C的全局变量语义).坚持使用示例3作为您的私有实例变量.

编码惯例

至于编码约定,由开发人员/团队决定是否使用下划线.我们的团队使用m_私有实例变量.Apple在他们的文档中建议使用下划线(这是合成属性的底层实例变量的命名方式).重要的是,要在整个代码中保持一致.

  • @Cupidvogel根本不是真的.我广泛使用它们来私下声明协议一致性和属性定义,而不会将它们暴露给公共头.这使公共标头保持干净和简洁,而不会使用属于私有实现细节的属性/协议进行污染. (3认同)

小智 8

类别和扩展之间的主要区别在于扩展期望您在主实现中实现方法,而对于类别,它可以在另一个实现中.似乎人们主要使用扩展主要用于私有方法.

正确.

使用类扩展来声明私有方法,而不是完全声明它(在两种情况下似乎都在运行中编译)之间的区别是什么?

也许只是关于未声明的选择器的编译器警告.(当然它运行正常 - 该方法已实现且确实存在.)另请注意,编译器需要声明(已知的,正确的函数签名)才能发出符合ABI标准的正确二进制代码.它对未声明的方法的假设(即它们返回id并接受可变参数)可能不正确 - 通过不兼容类型的指针调用函数是未定义的行为.

在扩展中声明ivars并在实现中直接声明它之间有什么区别?

在第四个例子中,它是一个全局C变量,它不是你的类的实例变量.

我什么时候应该在变量名称前加上下划线(_)?

无论何时,只要一直这样做.永远或永远.