在objective-c中应该如何实现私有成员和公共成员? [英] How should private and public members be implemented in objective-c?

查看:22
本文介绍了在objective-c中应该如何实现私有成员和公共成员?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I had some discussion related to the use of properties and instance variables at work, therefore I would like to find a wiki answer for that. Now, I know there's no real private member type in objective-c, everything is pretty much public. However, I'm a little bit concerned about the way we should design our classes and also to comply to OOP principles. I would like to hear opinions of these three design approaches:

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

A. According to various post and even to a new Stanford university iPhone development courses, you should always use properties everywhere you can. However IMHO, this approach brakes OOP design principles because in this case, all members become public. Why do I need to publish all my internal/local instance variables to outside? Also, there's some very little (but still) overhead if you use synthesized setters via properties, instead using local ivar directly. Here's a sample:

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

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

@end

B.另一种方法是在头文件中为私有成员声明 ivars(不声明相关属性),并在同一头文件中为公共成员声明纯属性(不声明相关 ivars).在这种情况下,ivars 将直接在类中使用.这种方法是有道理的,但不能利用属性的所有好处,因为我们必须在设置新值之前手动释放旧值.这是一个示例:

B. Another approach is to declare ivars in header file (without declaring relative properties) for private members, and in the same header file, to declare pure properties (without declaring relative ivars) for public members. In such case, ivars would be used directly in the class. This approach makes sense but not uses all benefits from properties because we have manually to release old values before setting the new ones. Here's a sample:

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

@property (nonatomic, retain) NSString *publicMemberWithProperty;

@end

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

C. To declare pure properties (without declaring relative ivars) for public members in header file, and to declare pure properties (without declaring relative ivars) for private members in private interface in implementation file. This approach IMHO is more clear than the first one, but the same question remains: why do we have to have properties for internal/local members? Here's a sample:

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

@property (nonatomic, retain) NSString *publicMemberWithProperty;

@end

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

@property (nonatomic, retain) NSString *propertyForPrivateMember;

@end

这个决定自由让我有点恼火,我想从各自的来源找到关于应该如何做的确认.但是,我无法在 Apple 文档中找到如此严格的声明,因此请发布指向 Apple 文档的链接(如果存在)或任何其他可以澄清这一点的理论.

This decision freedom annoys me a little bit and I would like to find a confirmation from respective sources about how things should be done. However, I was unable to find such strict statements in Apple docs on that, so please post a link to apple docs if any exists, or to any other theory that clears that.

推荐答案

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

By using class extensions you can have private properties.

类扩展语法很简单:

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

Inside the .m-file, that has the class, create a unnamed category:

.h

@interface OverlayViewController : UIViewController <VSClickWheelViewDelegate>
- (IBAction)moreButtonClicked:(id)sender;
- (IBAction)cancelButtonClicked:(id)sender;
@end

.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

现在您获得了私有成员属性的所有方面,而无需将它们暴露给公共.将合成属性写入编写的 getter/setter 应该没有开销,因为编译器将在编译时创建或多或少相同的属性.

Now you got all the aspects of properties for private members, without exposing them to public. There should be no overhead to synthesized properties to written getter/setters, as the compiler will create more or less the same at compile time.

请注意,此代码使用合成的 ivars.不需要在头文件中声明 ivar.

Note that this code uses synthesized ivars. No ivar declaration in the header is needed.

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

There is a nice cocoawithlove article, about this approach.

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

You also ask why to use properties for private ivars. There are several good reasons:

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

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

Since LLVM 3 it is also possible, to declare ivars in class extensions

@interface OverlayViewController (){
    NSInteger amount;
    NSArray *colors;
}
@end

甚至在实现块

@implementation OverlayViewController{
    NSInteger amount;
    NSArray *colors;
}
//…
@end

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

see "WWDC2011: Session 322 - Objective-C Advancements in Depth" (~03:00)

这篇关于在objective-c中应该如何实现私有成员和公共成员?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆