嗯,有人告诉我,我必须创建一个接受货币和价值的金钱类。该值应存储为2个整数,一个表示美元值,另一个表示美分。
* 它应该接受精确到十(2)个小数位的十进制值。 *
所以我想我必须限制美分值,以便它只接受1到2位整数。现在,我的问题是,我的导师告诉我,在构造函数中做其他事情是不好的做法。如果我不允许对构造函数做任何事情,我应该如何限制输入:
public class Money {
Currency currency;
int dollar;
int cents;
public Money(Currency currency, int dollar, int cents) {
super();
this.currency = currency;
this.dollar = dollar;
this.cents = cents;
}
..... other code.....
}
关于我应该如何实施我所指示的任何其他想法?为什么这是不好的做法,是否有办法定义约束而不会犯这种不良行为?
答案 0 :(得分:4)
您正在做的是验证构造函数的输入。虽然构造函数中的“其他东西”通常不是最优的,但做输入验证代码肯定是有道理的。以下是好模式IMO:
public Money(Currency currency, int dollar, int cents) {
this.currency = currency;
this.dollar = dollar;
// validate that cents is 0 to 99
if (cents < 0 || cents > 99) {
throw new IllegalArgumentException("Invalid cents value: " + cents);
}
this.cents = cents;
}
顺便说一句,除非扩展基类,否则在构造函数前面调用super()
是没有意义的。
答案 1 :(得分:0)
我认为人们为此提出的最常见原因是构造函数应该尽可能快地消除任何并发问题,并且万无一失,因为构造函数有点难以诊断。
在您的情况下,简单的数字验证就可以了。
但是,正如Marcello所说,您可以考虑编写验证函数并从构造函数中调用它们,以确保一致性。
答案 2 :(得分:0)
首先,如果使用构造函数获取无效对象,我认为验证并抛出异常并不是一种不好的做法。 也就是说,看看你的要求,可能已经足够好了。最后,您可以查看其他Money实现,例如this
答案 3 :(得分:-1)
在构造函数中添加代码是很糟糕的,你的导师是对的。 但是添加方法调用不是。
因此,您可以封装将限制另一个方法中的输入的操作,并在super之后立即调用它。
但是,我认为最好的做法是在将输入限制传递给构造函数之前处理输入限制。
在分离的类或接口类后面的代码中解析输入。 避免在代表某事物模型的类中使用代码操作,在本例中为“Money Model”
为什么这是不好的实践?
在面向对象中,您必须编写类,以便它们不会执行他们必须知道的更多操作。在这种情况下,您的类代表一个对象的模型,即金钱。为什么模型本身需要解析传递给它的构造函数的值? 得到它了 ?最好的实践是传递构造函数的值,已经解析和限制,以便该类只需要存储这些值。
例如,假设昨天您的约束发生了变化,您只需要更改解析部分,而不必在Money类中编写代码。
其他例子,有人必须使用你的金钱类,但它会有自己的约束,他所要做的只是使用他的解析类,而不是在金钱类中改变你的 希望它有所帮助。
答案 4 :(得分:-1)
如果美分值大于100,我会抛出ExceptionInInitializerError
。或者除以100,然后将商加到美元,余数加到美分。规范化和验证构造函数参数并不是一种不好的做法。