Java If-then-else-If输入分隔方法

Java If-then-else-If输入分隔方法,java,types,Java,Types,我有这样一种方法: //in Constant class MathObject add(MathObject addend){ if (addend instanceof Constant) { return new Constant(this.c + addend.c); } if (addend instanceof Variable) { return new Sum(this, addend); }

我有这样一种方法:

//in Constant class
MathObject add(MathObject addend){
    if (addend instanceof Constant)
    {
        return new Constant(this.c + addend.c);
    }
    if (addend instanceof Variable)
    {
        return new Sum(this, addend);
    }
    //...
}
//in Constant class
Constant add(Constant addend){
    return new Constant(this.c + addend.c);
}

Addition add(Variable addend){
    return new Sum(this, addend);
}
//...
//in Variable class
MathObject add(Product addend){
    if (addend.contains(this))
    {
        //code
        return new Product(newArray);
    }
    else
    {
        return new Sum(this, addend);
    }
}
new Constant(2).multiply(new Variable(1)).add(new Variable(1)).add(new Constant(1));
我想将该结构转换为如下内容:

//in Constant class
MathObject add(MathObject addend){
    if (addend instanceof Constant)
    {
        return new Constant(this.c + addend.c);
    }
    if (addend instanceof Variable)
    {
        return new Sum(this, addend);
    }
    //...
}
//in Constant class
Constant add(Constant addend){
    return new Constant(this.c + addend.c);
}

Addition add(Variable addend){
    return new Sum(this, addend);
}
//...
//in Variable class
MathObject add(Product addend){
    if (addend.contains(this))
    {
        //code
        return new Product(newArray);
    }
    else
    {
        return new Sum(this, addend);
    }
}
new Constant(2).multiply(new Variable(1)).add(new Variable(1)).add(new Constant(1));
这样,每个对象的正确方法将以更结构化的方式找到,更重要的是,实际返回类型是已知的。 问题是,在某些情况下,例如使用
产品
变量
进行的添加,不知道返回的对象是
添加
还是
产品
,如下所示:

//in Constant class
MathObject add(MathObject addend){
    if (addend instanceof Constant)
    {
        return new Constant(this.c + addend.c);
    }
    if (addend instanceof Variable)
    {
        return new Sum(this, addend);
    }
    //...
}
//in Constant class
Constant add(Constant addend){
    return new Constant(this.c + addend.c);
}

Addition add(Variable addend){
    return new Sum(this, addend);
}
//...
//in Variable class
MathObject add(Product addend){
    if (addend.contains(this))
    {
        //code
        return new Product(newArray);
    }
    else
    {
        return new Sum(this, addend);
    }
}
new Constant(2).multiply(new Variable(1)).add(new Variable(1)).add(new Constant(1));
我遇到的问题是,当我在
MathObject
上使用此类特定于类型的操作(即
add(Constant)
,而不是
newsum(Constant,variable)
)时,Java将考虑其声明的类型而不是实际的类型,抛出一个错误,如:
找不到适合的方法…
,对所有操作方法求和,并说明
MathObject
不在其中

为了澄清
常量
变量
和此处使用的所有其他对象自然扩展
MathObject
contains(Variable Variable)
是一种查找
产品
是否已包含
变量的方法

我们的想法是能够做到这样:

//in Constant class
MathObject add(MathObject addend){
    if (addend instanceof Constant)
    {
        return new Constant(this.c + addend.c);
    }
    if (addend instanceof Variable)
    {
        return new Sum(this, addend);
    }
    //...
}
//in Constant class
Constant add(Constant addend){
    return new Constant(this.c + addend.c);
}

Addition add(Variable addend){
    return new Sum(this, addend);
}
//...
//in Variable class
MathObject add(Product addend){
    if (addend.contains(this))
    {
        //code
        return new Product(newArray);
    }
    else
    {
        return new Sum(this, addend);
    }
}
new Constant(2).multiply(new Variable(1)).add(new Variable(1)).add(new Constant(1));
在这里,乘法和第一个加法操作将使用特定于类型的方法,但第二个操作将失败,因为第一个操作将返回一个
MathObject
,而不是一个特定的对象,并且Java不会检查方法选择的实际类型

这些是不同类的外观:

//These are all in different files, silly formatting doesn't allow me to split code sections.
public class Constant extends MathObject{
    public final double c;

    public Constant(double c){
        this.c = c;
    }

    //methods
}

public class Variable extends MathObject{
    public double v;

    public Variable(double v){
        this.v = v;
    }

    //methods
}

public class Sum extends MathObject{
    public MathObject summands;

    public Addition(MathObject... summands){
        this.summands = summands;
    }

    //methods
 }

我有什么遗漏吗?或者这是一种不好的做法(还有什么更好的做法)?这是可能的还是我注定要陷入丑陋的
if
语句链?

问题是你的抽象错误。你需要像这样的课程

public interface NumberExpr {
  NumberExpr apply();
  Number get();
}

public class Constant implements NumberExpr {
  final Number val;
}

public class Variable implements NumberExpr {
  final Map<String, Number> symbols;
  final String symbolName;
}

public class Addition implements NumberExpr {
  final NumberExpression op1;
  final NumberExpression op2;
}
也许您有计算顺序、优先级和关联性的规则,无论如何,您最终会得到如下结果:

new Multiplication(
    new Addition(new Variable("counter", ctx), new Variable("i", ctx))
  , new Constant(Math.PI)
)

也许您首先需要一个步骤来
.evaluate()
表达式,然后
.apply()
,无论如何,您只需调用
.apply()
然后
.get()即可得到最终结果
关于最终结果。

它在哪里抛出错误?正确的OO应该是反转调用,并在向具体类添加
后决定生成什么类型的
MathObject
,即
常量
具有
常量添加(MathObject addend)
方法,该方法使用
if(常数的加数实例)
-部分,
变量
有一个
MathObject加法(MathObject加数)
它使用上面的
变量
s
add
方法等。虚拟方法在运行时调度,但重载总是在编译时发生,这就是为什么他们甚至认为它本身不是一个好主意,因为它假装是一个比只允许
addinger(int)
addFloat(float)更强大的功能
addDouble(double)
。如果您需要这种功能,您可能会发现访问者模式很有用(基本上,它将导致@Smutje在其评论中定义的解决方案)。这是很久以前的事了,我刚刚尝试以两个MathObjects执行类似于
MathObject add的操作的方式实现访问者模式(MathObject that){返回that.add(this);}
。我希望这能帮助他们相互识别,但我一直遇到这样的问题,即只调用MathObjects的add,而不调用Constant,即使使用一个常量和另一个常量作为MathObject。有没有办法解决这个问题?或者我应该为每个MathObject实现一个accept方法,我想我下一步会尝试。这是不是我想做的,我想做的是这样的:
新变量(1)。乘法(新常量(2))。加法(新变量(2))。加法(新常量(1));
(任意)。顺便说一句,我试图通过对数组使用求和函数而不是重复加法来避免二进制操作。(我实际上将加法重命名为Sum,但我忘记了。)丑陋。这样,你需要有自己的数字超类型,并定义每个子类中的每个操作(顺便说一句,变量不能像你在上次注释中那样用常量表示)是的,它可以用一个常量来表示,它与常量的区别只是因为它的值不是最终值。如果您愿意,我可以链接到源代码,但我有三个版本,所有版本都没有完成。我已经对您的主要问题进行了评论。无论如何,对于双重分派,您可能会发现访问者模式在Java中很有用。基本上,您的MathContextxt将有一个适合每种类型的操作,每种类型都有一个带有MathContext对象作为参数的方法,它可以调用正确的方法