问题 比较在Objective C中拥有私有成员的不同方法


我来自C ++ / Java世界,很明显如何创建私有成员。但是,我在Objective C中看到了几种方法,我想听听cons和pros

1)在.h文件中将它们声明为@private

@interface MyClass : NSObject
{
    @private
    int someMember;  
}
@end

2)在.m文件中的接口中声明它们

@interface MyClass() {
    int someMember;  
}
@end

@implementation MyClass
@end

3)在实施中声明它们

@implementation MyClass {
     int someMember;  
}
@end 

什么是首选方法,为什么?我错过了其他方法吗?


1704
2017-08-23 21:04


起源

我希望你不会误以为Objective-C中的任何私有字段方案实际上都会保护该字段免受恶意访问。 - Hot Licks
是。据我所知,在目标c中,您可以在运行时访问所有内容。 - Victor Ronin


答案:


我的偏好是#3:

// MyClass.m
...
@implementation MyClass {
     int someMember;
}
@end

它允许您干净利落地抽象并最小化依赖性。

由于每个objc对象都是动态分配的,并且几乎没有物理依赖性,因此您可以拥有最快的构建时间和最丰富的对象表示,最小的编译开销(例如最小) #imports和身体依赖)。

抽象也是一个巨大的优势 - 私有是默认的,没有什么理由你应该偏离它,没有理由将内部暴露给其他人。这样可以非常好地隐藏它,同时确保类型安全不会受到影响。大加:您还可以轻松地在对象中声明C ++值,而不会让每个人都知道所有C ++库的依赖关系 - 不是PIMPL,不是全局范围内的结构,不是* void **,而是适当的 。这是一个很棒的编译防火墙。如果你从事大型C或C ++项目,你可能会感到高兴。

当然,如选项#2中所示,声明ivars会带来所有这些。所以它在很大程度上取决于您希望在何处以及如何看待变量。一个ivar声明是具体的,而一个属性可能是抽象的 - 所以我赞成将具体的具体化和接口分组,但无论如何; #2或#3是理想的,除非您需要向后兼容性。

如果你想要(伪)私有属性,我建议你在类继续中声明它们:

// MyClass.m
...
@interface MONClass ()
@property (nonatomic, copy) NSString * string;
@end

8
2017-08-23 21:19



我的偏好也是#3。你知道是否可以在子类中访问这些? - Stoff81
@justin是否适用于那些不仅仅是像int这样的原始类型的成员,还有像AVCaptureDevice等类的成员? - Bhargav
@Bhargav是的。 ARC甚至为这些成员提供支持。 - justin


你很方便地按照Objective-C的时间顺序列出它们。

我认为这主要是一个风格问题,但我会说99%的时间:

(1)不要将它们放在.h文件中,因为.h文件实际上是已发布的接口,没有理由发布实现细节;

(2)把它们放进去 @implementation 而不是在 @interface 基于避免无关语法的类扩展。你总是会有一个实现,你可能没有类扩展。


3
2017-08-23 21:20





如果有人想在不编辑的情况下使用MyClass,他们会快速读取头文件以弄清楚它是如何工作的。由于他们不关心您的私有变量,因此最好将它们排除在标题之外。

如果您需要私有属性或私有实现的协议,则需要在中使用类continuation .m 文件。

@interface MyClass () <SomeKindOfDelegate>
@property id someProperty;
@end

@implementation MyClass
@synthesize someProperty;
- (void)someKindOfDelegateMessage:(id)sender { }
@end

当你完成这个时,你也可以将你的成员变量放在延续中。

@interface MyClass () <SomeKindOfDelegate>
{
    int someMember;
}
@property id someProperty;
@end

@implementation MyClass
@synthesize someProperty;
- (void)someKindOfDelegateMessage:(id)sender { }
@end

0
2017-08-23 21:32