4

さまざまな単位 (体積、重量、距離) を表すさまざまなクラスがあり、変換値を基本型に格納するための値を持つ列挙型があります。

問題は、多くのコードの重複があることであり、それを回避する抽象クラスを作成するエレガントな方法があると確信しています。ただし、このクラスをどのように宣言すればよいかわかりません。ボリューム クラスは次のとおりです。

import java.math.BigDecimal;

import lombok.Data;

@Data
public class Volume {

public enum Unit
{
    CUBIC_METER(new BigDecimal("1")), // CUBIC_METER
    // 1 m3 = 61023.7 inch3
    CUBIC_INCH(new BigDecimal("61023.7"));
    private Unit(BigDecimal m3Value)
    {
        this.m3Value = m3Value;
    }

    public final BigDecimal m3Value;
}
// internally, we store the volume in m3
private final   BigDecimal  volumeInM3;

public Volume()
{
    volumeInM3 = BigDecimal.ZERO;
}

public Volume(final String volumeValue, final Unit volumeUnit)
{
    this(new BigDecimal(volumeValue), volumeUnit);
}

public Volume(final BigDecimal volumeValue, final Unit volumeUnit)
{
    if (volumeValue.signum() == 0)
    {
        volumeInM3 = BigDecimal.ZERO;
    }
    else
    {
        volumeInM3 = volumeValue.divide(volumeUnit.m3Value, NumberUtil.MC);
    }
}

/**
 * Return the volume in the unit given in param
 * @param volumeUnit
 * @return
 */
public BigDecimal getAs(final Unit volumeUnit)
{
    return volumeInM3.multiply(volumeUnit.m3Value, NumberUtil.MC);
}

public Volume add(final Volume volumeToAdd)
{
    BigDecimal newVolumeValue = volumeToAdd.volumeInM3.add(volumeInM3, NumberUtil.MC);
    return new Volume(newVolumeValue, Volume.Unit.CUBIC_METER);
}

public Volume divide(final Volume divisor)
{
    BigDecimal newVolumeValue = volumeInM3.divide(divisor.volumeInM3, NumberUtil.MC);
    return new Volume(newVolumeValue, Volume.Unit.CUBIC_METER);
}

public boolean isZero()
{
    if (volumeInM3.signum() == 0)
        return true;
    return false;
}

public boolean isEqual(final Volume another)
{
    if (volumeInM3.compareTo(another.volumeInM3) == 0)
        return true;
    return false;
}
}

そして、これは非常によく似た Weight クラスです:

import java.math.BigDecimal;

import lombok.Data;

@Data
public class Weight {

// the value stored with enum is the value used to convert the unit to kilogramm, 
// wich is the reference unit
public enum Unit
{
    KILOGRAM(new BigDecimal("1")),
    // 1 kg = 1000 g 
    GRAM(new BigDecimal("1000")),
    // 1 kg = 2.20462 pounds
    POUND(new BigDecimal("2.20462"));

    private Unit(BigDecimal kgValue)
    {
        this.kgValue = kgValue;
    }

    private final BigDecimal kgValue;
}

// internally, we store the weight inKg
private final BigDecimal weightInKg;

public Weight()
{
    weightInKg = BigDecimal.ZERO;
}

public Weight(final String weightValue, final Unit weightUnit)
{
    this(new BigDecimal(weightValue), weightUnit);
}

public Weight(final BigDecimal weightValue, final Unit weightUnit)
{
    if (weightValue.signum() == 0)
    {
        weightInKg = BigDecimal.ZERO;
    }
    else
    {
        weightInKg = weightValue.divide(weightUnit.kgValue, NumberUtil.MC);
    }
}

/**
 * Return the weight in the unit given in param
 * @param weightUnit
 * @return
 */
public BigDecimal getAs(final Unit weightUnit)
{
    return weightInKg.multiply(weightUnit.kgValue, NumberUtil.MC);
}

public Weight add(final Weight weightToAdd)
{
    BigDecimal newWeightValue = weightToAdd.weightInKg.add(weightInKg, NumberUtil.MC);
    return new Weight(newWeightValue, Weight.Unit.KILOGRAM);
}

public Weight divide(final Weight divisor)
{
    BigDecimal newWeightValue = weightInKg.divide(divisor.weightInKg, NumberUtil.MC);
    return new Weight(newWeightValue, Weight.Unit.KILOGRAM);
}
public boolean isZero()
{
    if (weightInKg.signum() == 0)
        return true;
    return false;
}

public boolean isEqual(final Weight another)
{
    if (weightInKg.compareTo(another.weightInKg) == 0)
        return true;
    return false;
}
}

ボリュームをインスタンス化する場合、ユーザーはユニットを明示的に指定する必要があります。

Volume myCubicMeter, myCubicInch;
myCubicMeter = new Volume("1", Volume.Unit.CUBIC_METER);
myCubicInch = new Volume("1", Volume.Unit.CUBIC_INCH);

私が達成しようとしているのは、すべてのメソッドを実装し、サブクラスに値で列挙を実装させる抽象クラスです。それを行う正しい方法は何ですか?

4

1 に答える 1

1

Java では、列挙は提供されたクラスのサブクラスであるEnumクラスです。

それらに共通の抽象祖先を与えることも、サブクラス化することもできません。列挙型のセットからコンパイル時定数を使用してユニットを参照する商品を本当に維持したい場合は、それを行うことはできません。

列挙の使用を破棄し、それらを通常のクラスとして宣言する場合は、他のすべてと同様に自由に行うことができます。

class VolumeUnit extends AbstractUnit {
  public static final VolumeUnit CUBIC_METER = new VolumeUnit(params);
  ..

  VolumeUnit(..) {
    ..
  }
}
于 2012-10-01T22:40:53.800 に答える