最近,我觉得需要编写一个Mutable<T>类,这样我就可以通过方法传递不可变的对象,然后可以更改这些方法的值。一些不可变类的示例(包括原始类型):
intlongshortbytedoublefloatString (虽然已经有了一个StringBuilder类BigInteger还有其他的。
类中有大量的重复,特别是原语数类型。我肯定有办法避免重复,但我想不出怎么回事。
很简单,对吧?
public class Mutable<T> {
protected T value;
public Mutable(T value) {
setValue(value);
}
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
}我还添加了一些额外的原语数字支持,以便:
Mutable<Integer> i = new Mutable<>(10);
i.setValue(i.getValue() + 10);变成:
MutableInteger i = new MutableInteger(10);
i.add(10);接口:
public interface MutableNumber<T extends Number> {
public abstract void add(T number);
public abstract T addAndGet(T number);
public abstract void sustract(T number);
public abstract T sustractAndGet(T number);
public abstract void multiply(T number);
public abstract T multiplyAndGet(T number);
public abstract void divide(T number);
public abstract T divideAndGet(T number);
}现在重复的部分:
public class MutableInteger extends Mutable<Integer> implements
MutableNumber<Integer> {
public MutableInteger(Integer value) {
super(value);
}
public void increment() {
value++;
}
public int incrementAndGet() {
return ++value;
}
public void decrement() {
value--;
}
public int decrementAndGet() {
return --value;
}
@Override
public void add(Integer number) {
value += number;
}
@Override
public Integer addAndGet(Integer number) {
value += number;
return value;
}
@Override
public void sustract(Integer number) {
value -= number;
}
@Override
public Integer sustractAndGet(Integer number) {
value -= number;
return value;
}
@Override
public void multiply(Integer number) {
value *= number;
}
@Override
public Integer multiplyAndGet(Integer number) {
value *= number;
return value;
}
@Override
public void divide(Integer number) {
value /= number;
}
@Override
public Integer divideAndGet(Integer number) {
value /= number;
return value;
}
}public class MutableLong extends Mutable<Long> implements MutableNumber<Long> {
public MutableLong(Long value) {
super(value);
}
@Override
public void add(Long number) {
value += number;
}
@Override
public Long addAndGet(Long number) {
value += number;
return value;
}
@Override
public void sustract(Long number) {
value -= number;
}
@Override
public Long sustractAndGet(Long number) {
value -= number;
return value;
}
@Override
public void multiply(Long number) {
value *= number;
}
@Override
public Long multiplyAndGet(Long number) {
value *= number;
return value;
}
@Override
public void divide(Long number) {
value /= number;
}
@Override
public Long divideAndGet(Long number) {
value /= number;
return value;
}
}public class MutableDouble extends Mutable<Double> implements
MutableNumber<Double> {
public MutableDouble(Double value) {
super(value);
}
@Override
public void add(Double number) {
value += number;
}
@Override
public Double addAndGet(Double number) {
value += number;
return value;
}
@Override
public void sustract(Double number) {
value -= number;
}
@Override
public Double sustractAndGet(Double number) {
value -= number;
return value;
}
@Override
public void multiply(Double number) {
value *= number;
}
@Override
public Double multiplyAndGet(Double number) {
value *= number;
return value;
}
@Override
public void divide(Double number) {
value /= number;
}
@Override
public Double divideAndGet(Double number) {
value /= number;
return value;
}
}public class MutableFloat extends Mutable<Float> implements
MutableNumber<Float> {
public MutableFloat(Float value) {
super(value);
}
@Override
public void add(Float number) {
value += number;
}
@Override
public Float addAndGet(Float number) {
value += number;
return value;
}
@Override
public void sustract(Float number) {
value -= number;
}
@Override
public Float sustractAndGet(Float number) {
value -= number;
return value;
}
@Override
public void multiply(Float number) {
value *= number;
}
@Override
public Float multiplyAndGet(Float number) {
value *= number;
return value;
}
@Override
public void divide(Float number) {
value /= number;
}
@Override
public Float divideAndGet(Float number) {
value /= number;
return value;
}
}关切事项:
和往常一样,任何事情都是受欢迎的。
发布于 2015-11-18 01:31:46
您的代码是一个很好的例子,说明什么时候应该使用原语;-)严肃地说,您有一个与未定义类型的原始算术相关的问题。像+和-这样的运算符是基于原语的(除了字符串级联),因此它们强烈地链接到特定的原语。代码是重复的,因为每个实现都有不同的原语组合。
在具有原始类型的其他语言中,如C或C++,您将遇到相同的问题,除非您也有无符号和有符号的变体,或者由于大量的转换而遭受其他问题。
公平地说,C++中的模板将有助于减少锅炉板,但语言本身将为您生成不同的代码实例。
那么,解决办法是什么?最好的解决方案是不封装原始操作。如果您需要执行1 + 1,那么就不要执行MutableInteger sum = new MutableInteger(1).add(1);。
或者,为了减少样板,选择一个单独的数据类型,它是其他类型的超集,并使用它。在这种情况下,可能是BigDecimal.嗯,BigDecimal是一个Number,但是会导致代码失败.
使用BigDecimal,您可以使用BigDecimal算法实现所有主要方法,然后有一个受保护的方法将其转换回基础类.(如果无法进行回播,则抛出异常?)
public abstract Mutable<T extends Number> {
protected abstract T backCast(BigDecimal result);
protected abstract BigDecimal getDecimal();
public T add(T number) {
return backCast(getDecimal().add(BigDecimal.valueOf(number.toString()));
}
.....
}发布于 2015-11-18 05:05:02
最近,我觉得需要编写一个可变的类,这样我就可以通过方法传递不可变的对象,然后可以更改这些方法的值。不可变类的一些示例(包括原语类型)
你的语言很混乱。我认为,您想要说的是,您感到需要编写一个Handle<T>类,这样您就可以对方法进行value objects,并能够在调用者中观察对这些值的更改。
(识别值对象的松散启发式:对对象执行操作将为您提供一个新的对象实例。)
public interface MutableNumber<T extends Number> {
public abstract T addAndGet(T number);
public abstract T sustractAndGet(T number);
public abstract T multiplyAndGet(T number);
public abstract T divideAndGet(T number);
}我确信Bertrand会告诉您这是一种代码气味;您的方法名称是在宣传方法改变了对象的状态并返回一个值。这不一定是错误的,但它暗示你应该重新审视你是否有正确的解决方案;这有时意味着重新审视你是否有正确的问题。
public Float sustractAndGet(Float number) {
value -= number;
return value;
}如果你要用这种方法,它真的应该照它说的去做:
public Float sustractAndGet(Float number) {
subtract(number);
return get();
}但回到顶端去
我觉得有必要写一个可变的类。
您可能不应该--这强烈地表明,您要替换的代码目前编写得很糟糕。对象只应很少负责执行计算和协调计算。相反,您应该将第一个对象传递给第二个对象。这是Builder模式的核心--导演协调应该发生的事情,而Builder跟踪计算。
因此,您可能有一个Builder接口,如下所示:
public interface NumberBuilder<T extends Number> {
void add(T number);
void sustract(T number);
void multiply(T number);
void divide(T number);
}但是,更有可能的是,界面本身应该更好地表达您真正想要实现的目标:
public interface AccountBuilder<T extends Number> {
void credit(T amount);
void debit(T amount);
void accrueInterest(T rate);
// ...
}https://codereview.stackexchange.com/questions/111065
复制相似问题