编码时,遇到以下情况:
我有一节课,我们称之为C
。它具有任意类型的属性A
,必须首先计算:
public class C {
private int A;
public C(...) {
...
}
public void calculateA() {
A = 42;
}
public int getA() {
}
}
我现在的问题是,如何正确实现getter getA
。我应该检查是否定义了A并抛出异常吗?
或者我应该在calculateA
中调用getA
,如果没有设置?
这类问题的最佳选择是什么?
编辑:好的,我举了一个不好的例子。无法在构造函数中计算A
,因为计算方法将返回同一个类的新实例,这将导致无限递归。
答案 0 :(得分:2)
我认为 -
public class C {
private int A = Integer.MIN_VALUE;
...
public int getA() {
if(A==Integer.MIN_VALUE )// Assume Integer.MIN_VALUE when it is not calculated
throw new RuntimeException();
return A;
}
}
它不能100%证明,因为假设Integer.MIN_VALUE
无法计算值。
使实例变量A
成为整数对象而不是原始int
,因此您可以将其设置为null,以便更容易确定状态。
答案 1 :(得分:1)
这是一个不好的例子,因为int是一种原始类型。它永远不会为空。它被初始化为零。
但您的观点对参考类型有效。
我认为允许对私有成员进行空引用是一种糟糕的设计。构造函数应该将对象初始化为100%准备就绪。
答案 2 :(得分:1)
这是一个设计问题,对于这个论坛来说有些不合适。
如果客户有责任在calculateA()
之前致电getA()
,那么getA()
如果尚未计算则会引发异常。 a
是原始的这一事实无关紧要,您可以初始化为无效值 - 例如如果它是一个长度类型的实体,那么将其初始化为-1 - 或使用另一个boolean
变量或使用一个为空的Integer
,无论如何。
了解这会创建时间依赖性 - 客户端需要以固定顺序调用方法。这通常是不受欢迎的,但可能存在合理的情况,您必须在致电Car.start()
之前致电Car.stop()
。
另一方面,如果C
“拥有”A
,那么它有责任计算它。它可以通过以下几种方式实现:
<init>
中,如果所有必要信息都是可用的calculateA()
致电A
。 getA()
可能是误导性名称。 答案 3 :(得分:0)
这取决于。如果计算是静态的,你也可以从构造函数中调用calculateA()函数。
public C(...) {
...
calculateA()
}
public void calculateA() {
A = 42;
}
如果getter()的合约规定只返回A
的有效值和计算值,请在返回之前计算A
。
如果由于某种原因无法计算A
,并且如果在计算任何进一步使用无效A
之前停止执行是有意义的,则抛出异常。