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加数)
它使用上面的变量sadd
方法等。虚拟方法在运行时调度,但重载总是在编译时发生,这就是为什么他们甚至认为它本身不是一个好主意,因为它假装是一个比只允许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对象作为参数的方法,它可以调用正确的方法