Objective-C: 将所有访问器替换为只读属性是否可行?

3
如果我在Objective-C中将所有的访问器(类似于const方法的get方法)替换成只读属性,是否存在任何缺点?它们是否可以互换使用?
我更喜欢使用只读属性进行文档编写和可读性。
作为一名来自C ++的开发者,我正在考虑用只读属性替换掉所有的const方法(不可变方法)。
如果我坚持这个惯例,那么我可以自动假定任何常规方法都会改变状态(在C ++中是非const方法)。从函数式编程的角度来看,知道只读属性不会改变任何状态(没有副作用)是有用的。

你是在谈论属性还是方法?这个问题似乎有点令人困惑。你能提供一个代码示例来说明你想要实现什么吗? - Anurag
@Anurag - 在标准面向对象编程术语中,访问器是一个常量、不可变的类似于get方法的方法。在我看来,它类似于只读属性 - 这就是为什么我发布这个问题的原因。 - kfmfe04
5个回答

3
当然可以这样实现,如果您选择这样做,从上下文来看,这样做可能有很多优点。需要注意的缺点是生成的属性的成本可能会更高,它们可能比非原子属性慢20倍以上。如果(例如)您的属性不可重新分配,那么执行所有这些引用计数循环/自动释放活动将是巨大的浪费。另一个(轻微的)缺点是,您经常会发现自己要实现或声明私有setter。

2

它们可以以相同的方式访问(点语法或方法语法)。做任何感觉最好的事情。虽然我更喜欢将方法作为方法,当它们执行(一些)逻辑时。如果它只是一个访问器/获取器返回一些数据,那么属性更合适。


对于一个好的点(点语法或方法语法),加1分。我更喜欢隐藏实现,以至于消费者不知道逻辑是否必要 - 但有时,让消费者知道调用是否会改变对象是有用的。 - kfmfe04
一个可读属性,却会改变对象本身,这不是非常奇怪吗?我想不出任何用例。但我同意,有时属性访问可能涉及一些逻辑。但这实际上取决于用例。那么你想要在这里得到什么答案?你有一个具体的例子吗? - calimarkus
@jaydee3 懒加载是一个经常使用的例子。 - justin
1
是的,这里涉及到逻辑。好的。但没有真正的自我变异。只是向其中添加了图像。是的...你可以将其视为变异。现在不是很重要。 :) - calimarkus
@jaydee3 嗯 - 我不知道为什么你坚持认为更改对象的成员/变量不符合“真正”的突变。所以...也许你应该解释一下为什么它不是“真正”的突变。 - justin
显示剩余4条评论

1
这与键值编码有关。请看以下内容:
@interface Boat : NSObject {
   NSString *name;
}
@property (nonatomic, retain) NSString *name;
@end

而且...

@interface Boat
@synthesize name;
@end

在这种情况下,合成器所做的是创建两种方法:

-(NSString *)name;
-(void)setName;

它使用所谓的“驼峰命名法”来命名选择器,在将ivar的第一个字母改为大写后,在setter的前面添加“set”。getter的名称只是ivar的名称。

如果您的ivar名称和现有方法遵循此模式,则使用属性替换手写访问器将无缝工作,无论您使用点语法还是显式消息:

boat.name = @"Pequod" 编译为 [boat setName:@"Pequod"]。而 boat.name 编译为 [boat name]

如果您的访问器没有这样命名,则需要重新设计代码中使用它们的地方以匹配此模式。根据此模式编码是所有Objective-C / Cocoa编程的最佳方法。


1

是的,它们是可互换的。

@interface MyClass : NSObject
@property (nonatomic, readonly) NSString *myStr;
@end

是相同的

@interface MyClass : NSObject
-(NSString *)myStr;
@end
@interface MyClass() { NSString *_myStr } 
@end
@implementation MyClass
-(NSString *)myStr { return _myStr; }
@end

虽然在代码中看不到,但属性确实创建了一个可访问的myStr方法。在这两种情况下,您都可以使用self.myStr[self myStr]来调用该方法。

顺便说一句:如果您正在使用iOS 6,则无需包含@synthesize语句。否则,您需要在实现文件中编写:@synthesize myStr = _myStr;


1

您仍然需要一些方法来设置它们,具有适当的setter通常非常方便,以实现自动内存管理目的。类扩展是为了实现这个目的而创建的;公开只读,私有可读写。

Foo.h:

@interface Foo : NSObject
@property(readonly, copy) NSString* bar;
@end

Foo.m: @interface Foo() @property(readwrite, copy) NSString* bar; @end

Foo.m: @interface Foo() @property(readwrite, copy) NSString* bar; @end
@implementation Foo
... no need to @synthesize ...
- randomMethod

{ [self setBar: @"bas"]; ... self.bar; _bar = [NSString stringWithFormat: @"%@ %@", [self bar], self.bar]]; }

是的,您需要在@interface声明中使用copy。即使在只读属性上,接口中的修饰符也可以修改getter和setter的代码生成。

您可能还会发现我的回答对这个问题相关。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接