我有一个接口Value实现的层次结构,将大大简化它。假设我有两个实现,NumberValue和StringValue。
有一个平均操作仅对带有签名的NumberValue有意义
NumberValue平均值(NumberValue numberValue){
...
}
在创建了这样的变量并在各种集合中使用它们之后的某个时候,我需要平均一个我知道只是NumberValue类型的集合,我认为有三种可能的方式可以做到这一点:
非常复杂的通用签名,可以在编译时保留类型信息(我现在正在做什么,并且导致难以维护代码)
将操作移至“值”级别,并:为StringValue抛出unsupportedOperationException,并为NumberValue进行强制转换。
在我确定自己具有NumberValue的位置进行转换,使用稍微复杂一些的泛型来确保这一点。
是否有人有更好的想法或对最佳实践的建议?
最佳答案
正如@tafa所说,在我看来,接口是一个不错的选择。根据您对average
的签名,我提出了以下内容。
平均价值
public interface AveragableValue<T> extends Value
{
public T average(T value);
}
数值
public class NumberValue implements AveragableValue<NumberValue>
{
private int _n;
public NumberValue(int n)
{
this._n = n;
}
@Override
public void doSomething()
{
// from Value interface
}
@Override
public NumberValue average(NumberValue value)
{
return new NumberValue((this._n + value._n) / 2);
}
}
然后,您可以将集合设为
AveragableValue
类型。在您的代码中,您必须已经在某处具有某种if/else
子句以区分NumberValue
和StringValue
以确定是否调用average
。因此,我不认为这会变得更加复杂。层次结构有意义-AveragableValue
是Value
的子类型,而NumberValue
是AveragableValue
的类型。但是,
average
的签名看起来不正确。它仅接受2个值(this
和参数)并将其取平均值。然后,您将丢失之前平均的总事物数。因此,假设整数作为值(如我所做的那样),则如下所示:(new NumberValue(4)).average(new NumberValue(8)).average(new NumberValue(12));
将为您提供值
9
而不是8
。这是你想要的吗?就像您对集合所做的那样,它使许多迭代计算变得很糟糕。如果您向我们展示了一些代码-这些类的使用方式,保存它们的集合,您现在的平均状况-我可能会给出更好的答案。