数字系统类的继承层次结构

时间:2015-03-10 11:58:52

标签: java oop inheritance

对于数学表达式的符号表示,我正在尝试构建数字系统类的层次结构。

除了IntegerReal之外,我还需要RationalComplex等类。我希望所有这些类能够相互无缝地互操作。

e.g。向Complex添加Integer号码会产生Complex个号码。


我让所有这些都实现了Number接口。 (不是java.lang.Number

为了能够添加不同类型的数量,我尝试制作如下的层次结构。

  

Integer延伸Rational延伸Real延伸Complex

  • 这会使Integer不必要地存储虚部等。这种开销是不受欢迎的。
  • 同样允许访问Integer的虚部也是不合适的。

任何人都可以建议更好的设计,避免开销,仍然可以进行互操作吗?

3 个答案:

答案 0 :(得分:1)

我宁愿创建一个类似getRealPart()和getImaginaryPart()的界面。然后你的整数可以简单地为getImaginaryPart()返回0。那是因为你希望Integer能够成为"复杂,但您不希望Integer包含Complex的内部实现。

答案 1 :(得分:1)

我在这里看不到问题。实数是一个复数,整数是实数。复数可以表示为a + bi,整数是复数,因此a是整数b = 0。所以每个整数都有b,它等于0。

但是,您可以考虑使用组合(和接口)而不是继承:

interface Complex {

    Real a();

    Real b();

}

interface Real extends Complex {

    @Override
    default Real b() {
        return new Integer(0);
    }

}

class Integer implements Real {

    public Integer(int value) {
        // ...
    }

    @Override
    public Real a() {
        return this;
    }

    // ...

}

这种方法的缺点是Integer类可以覆盖b()方法,因此可能继承会更好,因为您可以在方法上使用final关键字:

abstract class Complex {

    abstract Real a();
    abstract Real b();

}

abstract class Real extends Complex {

    @Override
    public final Real b() {
        return new Integer(0);
    }

}

class Integer extends Real {

    public Integer(int value) {
        // ...
    }

    @Override
    public Real a() {
        return this;
    }

    // ...

}

我自己试图对它进行建模,我在下面提出了这个可怕的代码。由于以下问题,我对此并不满意:

  • Interface - InterfaceImpl反模式
  • IntegerNumber包含realPart()numerator()denominator()
  • 等方法
  • 一些数字(复杂和理性)使用其他数字,而其他数字(实数和整数)使用Java原语

代码:

public class Test {

    public static void main(String[] args) {
        ComplexNumber complexOne = new ComplexNumber(new RealNumber(1.25), new RealNumber(3));
        ComplexNumber complexTwo = new ComplexNumber(new RealNumber(7), new RealNumber(18.875));

        System.out.println("adding two complex numbers:");
        System.out.println(complexOne.add(complexTwo));


        RealNumber realOne = new RealNumber(15.125);
        RealNumber realTwo = new RealNumber(7.375);

        System.out.println("adding two real numbers:");
        System.out.println(realOne.add(realTwo));
        System.out.println(realTwo.add(realOne));

        System.out.println("adding complex and real number:");
        System.out.println(complexOne.add(realOne));
        System.out.println(realOne.add(complexOne));


        RationalNumber rationalOne = new RationalNumber(new IntegerNumber(1), new IntegerNumber(2));
        RationalNumber rationalTwo = new RationalNumber(new IntegerNumber(1), new IntegerNumber(3));

        System.out.println("adding two rational numbers:");
        System.out.println(rationalOne.add(rationalTwo));


        IntegerNumber integerOne = new IntegerNumber(6);
        IntegerNumber integerTwo = new IntegerNumber(7);

        System.out.println("adding two integers:");
        System.out.println(integerOne.add(integerTwo));

        System.out.println("adding real number and integer:");
        System.out.println(integerOne.add(realOne));
        System.out.println(realOne.add(integerOne));

        System.out.println("adding complex number and integer:");
        System.out.println(integerOne.add(complexOne));
        System.out.println(complexOne.add(integerOne));
    }

}

// interfaces

interface Complex {

    Real realPart();
    Real imaginaryPart();

    default Complex add(Complex other) {
        return new ComplexNumber(
                this.realPart().add(other.realPart()),
                this.imaginaryPart().add(other.imaginaryPart())
        );
    }

}

interface Real extends Complex {

    double asDouble();

    @Override
    default Real imaginaryPart() {
        return new IntegerNumber(0);
    }

    default Real add(Real other) {
        return new RealNumber(this.asDouble() + other.asDouble());
    }

}

interface Rational extends Real {

    Integer numerator();
    Integer denominator();

    @Override
    default Real realPart() {
        return new RealNumber(1.0d * numerator().asInt() / denominator().asInt());
    }

    @Override
    default double asDouble() {
        return realPart().asDouble();
    }

    default Rational add(Rational other) {
        return new RationalNumber(
                this.numerator().multiply(other.denominator()).add(this.denominator().multiply(other.numerator())),
                this.denominator().multiply(other.denominator())
        );
    }

}

interface Integer extends Rational {

    int asInt();

    @Override
    default Integer numerator() {
        return new IntegerNumber(asInt());
    }

    @Override
    default Integer denominator() {
        return new IntegerNumber(1);
    }

    default Integer add(Integer other) {
        return new IntegerNumber(this.asInt() + other.asInt());
    }

    default Integer multiply(Integer other) {
        return new IntegerNumber(this.asInt() * other.asInt());
    }

}

// implementations

class ComplexNumber implements Complex {

    private final Real realPart;
    private final Real imaginaryPart;

    public ComplexNumber(Real realPart, Real imaginaryPart) {
        this.realPart = realPart;
        this.imaginaryPart = imaginaryPart;
    }

    @Override
    public Real realPart() {
        return realPart;
    }

    @Override
    public Real imaginaryPart() {
        return imaginaryPart;
    }

    @Override
    public String toString() {
        return String.format("%s + %si", realPart, imaginaryPart);
    }

}

class RealNumber implements Real {

    private final double value;

    public RealNumber(double value) {
        this.value = value;
    }

    @Override
    public Real realPart() {
        return this;
    }

    @Override
    public double asDouble() {
        return value;
    }

    @Override
    public String toString() {
        return "" + value;
    }

}

class RationalNumber implements Rational {

    private final Integer numerator;
    private final Integer denominator;

    public RationalNumber(Integer numerator, Integer denominator) {
        this.numerator = numerator;
        this.denominator = denominator;
    }

    @Override
    public Integer numerator() {
        return numerator;
    }

    @Override
    public Integer denominator() {
        return denominator;
    }

    @Override
    public String toString() {
        return String.format("%s/%s", numerator, denominator);
    }

}

class IntegerNumber implements Integer {

    private final int value;

    public IntegerNumber(int value) {
        this.value = value;
    }

    @Override
    public int asInt() {
        return value;
    }

    @Override
    public String toString() {
        return "" + value;
    }

}

我想知道接口是否应该是实现方法为final的抽象类。最后,我认为最好只使用简单继承并忽略每个整数都有一个虚部的字段这一事实。

我希望这会给你一些想法。

答案 2 :(得分:1)

public interface Numberr {
    public Numberr plus(Numberr n);
    public Numberr minus(Numberr n);
    public Numberr multiply(Numberr n);
    public Numberr sqrt();
    ...

    public Class<? extends Numberr> getType();
}

/////////////////////////////////////////////

public class Integerr implements Numberr {

    protected BigInteger value;

    @Override
    public Numberr plus(Numberr n) {
       if (n instanceof Integerr) {
           return value.add(n.value);
       } else {
           // in case of more broad argument type, use method of that class
           return n.plus(this); 
       }
    }

    ....
}

///////////////////////////////////////////////

public class Rational implements Numberr {

   protected BigInteger numerator;
   protected BigInteger denominator;

   @Override
   public Numberr plus(Numberr n) {
       if (n instance of Integerr) {
           return new Rational(numerator.multiply(n.value), denominator); 
       } else if (n instanceof Rational) {
           return new Rational(numerator.multiply(n.denominator).add(n.numerator.multiply(denominator)), denominator.multiply(n.denominator));
       } else {
           return n.plus(this);
       }
   }

   ....

}