【发布时间】:2016-03-01 22:28:24
【问题描述】:
上下文
在使用 Objective-C 编程时,我习惯于从不直接与实例变量交互。相反,我使用访问器方法作为方法和实例变量之间的桥梁。 @property 关键字和点符号非常适合实现这一点,同时保留代码外观。声明属性时,也会创建实例变量及其访问器方法。我可以通过覆盖访问器方法自定义任何行为或决定使用或不使用实例变量。
我最近开始尝试使用 Lombok @Getter 和 @Setter 注释在 Java 中实现类似(不完全相同)的系统。一切正常,但有一个小细节困扰着我:如果我想声明一个没有实例变量的只读属性,我不能声明该变量。这句话听起来很明显,但这是代码组织的问题:我希望能够在“属性”部分列出所有属性。
示例
使用实际示例可能更容易解释这种情况。这是 Objective-C 中的代码片段:
#pragma mark - Properties
@property (nonatomic, strong) Foo foo;
@property (nonatomic, strong) Bar bar;
@property (readonly) Baz baz;
#pragma mark - Getters / Setters
-(Bar)getBar {
// Override bar getter. For example, perform lazy instantiation
if(_bar == nil) {
_bar = [[Bar alloc] init];
}
return _bar;
}
-(Baz)getBaz {
// Override baz getter. For example, get baz from foo
return self.foo.baz;
}
#pragma mark - Methods
-(void)doSomethingWithFooBarAndBaz {
// Get log message
NSString* logMessage = [NSString stringWithFormat:@"Foo: %@ Bar: %@ Baz: %@",
self.foo, self.bar, self.baz];
// Log
NSLog(logMessage);
}
我写的Java版本如下:
@Accessors(prefix = "_")
...
// Properties
@Getter @Setter private Foo _foo;
@Setter private Bar _bar;
[THE PROBLEM IS HERE - I want to know that the baz property exists without
having to declare an instance variable for it]
// Getters / Setters
private Bar getBar() {
// Implement bar getter. For example, perform lazy instantiation
if(_bar == null) {
_bar = new Bar();
}
return _bar;
}
private Baz getBaz() {
// Implement baz getter. For example, get baz from foo
return getFoo().getBaz();
}
// Methods
private void doSomethingWithFooBarAndBaz {
// Get log message
String logMessage = "Foo: " + getFoo().toString() +
" Bar: " + getBar().toString() +
" Baz: " + getBaz().toString();
// Log
System.out.print(logMessage);
}
问题
有没有办法做到这一点?现在我正在声明一个实例变量并对其进行注释,如下所示:
@Getter @Setter private Foo _foo;
@Setter private Bar _bar;
// private Baz _baz;
但是感觉不对。我想知道是否有一个注释使实例变量在编译时和运行时不可用,从而使其纯粹是信息性的,所以我可以这样做:
@Getter @Setter private Foo _foo;
@Setter private Bar _bar;
@[ANNOTATION] private Baz _baz;
有什么想法吗?此外,这种方法是否违反任何 Java 最佳实践?
【问题讨论】:
-
这还不清楚。为什么你认为声明
_baz,它是只读的,不应该通过只声明一个getter来完成?据推测,它的值将在构造过程中设置或作为某些其他操作的副作用。这就是@property (readonly) Baz baz;完成的工作,那么@Getter private Baz _baz;有什么问题? -
@JimGarrison 在这种特殊情况下,每次调用
getBaz()getter 时都应该计算来自baz的值(Swift 世界中的计算属性),而不是将结果缓存在实例上多变的。如果我按照您的建议编写@Getter private Baz _baz;,我将创建一个未使用的变量,因为_baz不会用于getter 实现。我不想要这种行为。 -
只是为了说明,在 Objective-C 中,声明一个只读属性 (
@property (readonly) Baz baz) 并实现它的 getter (-(Baz)getBaz) 不会创建_baz实例变量 -
我不知道你用的是哪个注解库,但是为什么你不能在不声明实例变量的情况下实现
getBaz()呢?注解可以应用到方法上吗? -
考虑我之前评论中的 Objective-C 示例(只读属性声明和 getter 实现)。如果我删除属性声明,代码将以完全相同的方式工作。这是因为在这种情况下,属性声明只是提供信息。这就是我想要的:关于属性的信息。在Java中,如果我不声明实例变量,确实一切都会工作,但我无法直观地知道有一个属性,除非我检查所有的getter,这不是我想要的。跨度>
标签: java objective-c lombok