对于数学表达式的符号表示,我正在尝试构建数字系统类的层次结构。
除了Integer
和Real
之外,我还需要Rational
和Complex
等类。我希望所有这些类能够相互无缝地互操作。
e.g。向Complex
添加Integer
号码会产生Complex
个号码。
我让所有这些都实现了Number
接口。 (不是java.lang.Number
)
为了能够添加不同类型的数量,我尝试制作如下的层次结构。
Integer
延伸Rational
延伸Real
延伸Complex
Integer
不必要地存储虚部等。这种开销是不受欢迎的。Integer
的虚部也是不合适的。任何人都可以建议更好的设计,避免开销,仍然可以进行互操作吗?
答案 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()
代码:
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);
}
}
....
}