数字系统类的继承层次结构 [英] Inheritance hierarchy for number system classes

查看:93
本文介绍了数字系统类的继承层次结构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

For symbolic representation of mathematical expressions, I am trying to build a hierarchy of number system classes.

除了 Integer Real ,我还需要类似 Rational Complex 。我希望所有这些类能够相互无缝地互操作。

In addition to Integer and Real, I also need classes like Rational and Complex. I want all of these classes to inter-operate seamlessly with each other.

例如。将 Complex 数字添加到 Integer 将提供 Complex 数字等。

e.g. Adding a Complex number to an Integer would give a Complex number etc.

我做了所有这些来实现 Number 界面。 (NOT java.lang.Number

I made all of them to implement the Number interface. (NOT java.lang.Number)

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

For being able to add numbers of different types, I tried making hierarchy like following.


整数 extends Rational extends Real extends Complex

Integer extends Rational extends Real extends Complex




  • 这使得整数不必要地存储虚部等。这种开销是不受欢迎的。

  • 同样允许访问 Integer 的虚部。似乎不合适。

    • This makes an Integer to unnecessarily store imaginary part etc. This overhead is undesired.
    • Also allowing access to imaginary part of an Integer seems improper.
    • 任何人都可以建议更好的设计,避免开销并且仍然可以进行互操作吗?

      Can anyone suggest a better design where overhead is avoided and interoperation is still possible?

      推荐答案

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

      I don't see a problem here. Real number is a complex number, integer is a real number. Complex number can be expressed as a + bi and an integer is a complex number, such that a is an integer and b = 0. So every integer has b and it is equal to 0.

      但是你可以考虑使用组合(和接口)过继承:

      You may however consider using composition (and interfaces) over inheritance:

      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 关键字:

      The disadvantage of this approach is that Integer class can override b() method, so maybe inheritance would be better, because you can use final keyword on the method:

      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;
          }
      
          // ...
      
      }
      

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

      I have tried to model it myself and I came up with this terrible code below. I am not happy about it, because of the following problems:


      • 界面 - InterfaceImpl antipattern

      • IntegerNumber 包含等方法realPart() numerator() denominator()

      • 一些数字(复杂和理性)使用其他数字,而其他数字(实数和整数)使用Java原语

      • Interface - InterfaceImpl antipattern
      • IntegerNumber has methods such as realPart() or numerator() and denominator()
      • some numbers (complex and rational) use other numbers, while others (real and integer) use Java primitives

      代码:

      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。最后,我认为最好只使用简单继承并忽略每个整数都有一个虚部的字段的事实。

      I am wondering whether interfaces should be abstract classes with implemented methods being final. In the end, I think it may be better to just go with simple inheritance and ignore the fact that every integer will have a field for imaginary part.

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

      I hope this will give you some ideas.

      这篇关于数字系统类的继承层次结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆