如何在目标c中实施私人和公共成员?

Cen*_*ion 23 oop cocoa-touch properties objective-c ios

我有一些关于在工作中使用属性和实例变量的讨论,因此我想找到一个wiki的答案.现在,我知道在objective-c中没有真正的私有成员类型,一切都是公开的.但是,我有点担心我们应该如何设计我们的类以及遵守OOP原则.我想听听这三种设计方法的意见:

A.根据各种帖子甚至是新的斯坦福大学iPhone开发课程,你应该随时随地使用属性.然而恕我直言,这种方法制定了OOP设计原则,因为在这种情况下,所有成员都会公开.为什么我需要将所有内部/本地实例变量发布到外部?此外,如果您通过属性使用合成设置器,而不是直接使用本地ivar,则会有一些(但仍然)开销很小.这是一个示例:

//==== header file =====//
@interface MyClass : NSObject

@property (nonatomic, retain) NSString *publicMemberWithProperty;
@property (nonatomic, retain) NSString *propertyForPrivateMember;

@end
Run Code Online (Sandbox Code Playgroud)

B.另一种方法是在声明头文件的ivars(不宣相关性质)为私有成员,并且以相同的头文件,申报纯特性(不宣相对的ivars)为公众成员.在这种情况下,ivars将直接在课堂上使用.这种方法很有意义但不会使用属性的所有好处,因为我们在设置新值之前手动释放旧值.这是一个示例:

//==== header file =====//
@interface MyClass : NSObject{
  NSString *_privateMember;
}

@property (nonatomic, retain) NSString *publicMemberWithProperty;

@end
Run Code Online (Sandbox Code Playgroud)

C.在头文件中为公共成员声明纯属性(不声明相对的ivars),并在实现文件的私有接口中为私有成员声明纯属性(不声明相对的ivars).这种方法恕我直言比第一种更明确,但同样的问题仍然存在:为什么我们必须拥有内部/本地成员的财产?这是一个示例:

//==== header file =====//
@interface MyClass : NSObject

@property (nonatomic, retain) NSString *publicMemberWithProperty;

@end

//==== implementation file =====//
@interface MyClass()

@property (nonatomic, retain) NSString *propertyForPrivateMember;

@end
Run Code Online (Sandbox Code Playgroud)

这个决定的自由让我感到很恼火,我想从各自的消息来源中找到关于应该如何做的确认.但是,我无法在Apple文档中找到这样严格的声明,所以请发布一个链接到Apple docs(如果有的话),或者发布任何其他清除它的理论.

Vik*_*ica 21

通过使用类扩展,您可以拥有私有属性.

类扩展语法很简单:

在具有该类的.m文件中,创建一个未命名的类别:

.H

@interface OverlayViewController : UIViewController <VSClickWheelViewDelegate>
- (IBAction)moreButtonClicked:(id)sender;
- (IBAction)cancelButtonClicked:(id)sender;
@end
Run Code Online (Sandbox Code Playgroud)

.M

#import "OverlayViewController.h"

@interface OverlayViewController ()
@property(nonatomic) NSInteger amount;
@property(retain,nonatomic)NSArray *colors;
@end

@implementation OverlayViewController
@synthesize amount = amount_;
@synthesize colors = colors_;

//…

@end
Run Code Online (Sandbox Code Playgroud)

现在,您可以获得私有成员的所有属性,而不会将其暴露给公众.写入getter/setter的合成属性应该没有开销,因为编译器在编译时会创建或多或少的相同内容.

请注意,此代码使用合成的ivars.标题中不需要ivar声明.

关于这种方法,有一篇很好的cocoawithlove文章.

您还会问为什么要使用私有ivars的属性.有几个很好的理由:

  • 属性负责所有权和内存管理.
  • 在未来的任何时候你都可以决定写一个自定义的getter/setter.即重新加载一个tableview,一旦新设置了NSArray ivar.如果您因此使用了属性,则不需要进行其他更改.
  • 键值编码支持属性.
  • public readonly属性可以重新声明为私有readwrite属性.

编辑
从LLVM 3开始,也可以在类扩展中声明ivars

@interface OverlayViewController (){
    NSInteger amount;
    NSArray *colors;
}
@end
Run Code Online (Sandbox Code Playgroud)

甚至在实施区块

@implementation OverlayViewController{
    NSInteger amount;
    NSArray *colors;
}
//…
@end
Run Code Online (Sandbox Code Playgroud)

参见"WWDC2011:会议322 - Objective-C深度进展"(~03:00)