3
\$\begingroup\$

I have got it working in a way so that there is one superclass, MathObject. In this implementation there is only a Constant subclass. I was forced to implement an abstract MathObject add(MathObject that) and an abstract MathObject add(Constant that) for reasons.

I would like to get that abstract MathObject add(Constant) out of MathObject because its already in Constant and I would have to update MathObject for each object I add.

I'd like to focus on maintainability and expandability first before adding too much features (this is my third or so attempt).

public class MathMain{
    public static void main(String[] args){
        Constant constant = new Constant(1);
        constant.add(constant);
        MathObject mathObject = (MathObject)constant;
        constant.add(mathObject);
        constant.add((Constant)mathObject);
        mathObject.add(constant);
    }
}

public abstract class MathObject{
    public abstract MathObject add(MathObject that);

    public abstract MathObject add(Constant that);

    public abstract MathObject substract(MathObject that);

    public abstract MathObject substract(MathObject that);

    public abstract double evaluate();
}

public class Constant extends MathObject{
    public final double c;

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

    public MathObject add(MathObject that){
        return that.add(this);
    }

    public MathObject substract(MathObject that){
        return that.substract(this);
    }

    public Constant add(Constant addend){
        return new Constant(c + addend.c);
    }

    public Constant substract(Constant subtrahend){
        return new Constant(c - subtrahend.c);
    }

    public double evaluate(){
        return c;
    }
}
\$\endgroup\$
  • 1
    \$\begingroup\$ Check out the instanceof keyword. Also: subtract has only one s. \$\endgroup\$ – AlexR Mar 20 '16 at 14:58
  • \$\begingroup\$ Please don't make corrections that were already addressed in answers. \$\endgroup\$ – Jamal Mar 20 '16 at 16:56
  • \$\begingroup\$ This inspired me to try to make my own basic CAS, and let me just say that this is not easy. I don't quite know how to decouple the specific classes from the code, and I'm not convinced that doing so will necessarily make the code cleaner. \$\endgroup\$ – Justin Mar 20 '16 at 21:30
3
\$\begingroup\$

You have a compile error since MathObject has 2 identical substract methods; I assume this is a copy-paste error and the second should have Constant instead of MathObject as its parameter.


substract -> subtract.


MathObject only has abstract methods. If it is not going to give any common implementation, I would recommend making it an interface instead of an abstract class, as that would allow implementations to extend a different class as well.

Additionally, I would change evaluate() to doubleValue(), similar to the identically named method in the Number class. What if you want to have a CAS system that computes using BigDecimal, but you want to reuse your code?


Constant has a public final double c. That should be private; you (almost) never want to have a public field for a class.


The Big Problem

There is currently a rather big problem with your design: MathObject treats Constants differently from MathObjects. This should not be the case. Rather, the Constant class should comply with the MathObject interface:

public class Constant implements MathObject {
    private final double c;

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

    // Always add this when you override a method. It doesn't enforce anything
    // in Java's compile (unfortunately), but you will get a warning if you have
    // a method with @Override that doesn't actually override anything. However,
    // what this annotation does do is that it documents. If I come in and look at your
    // code, it is immediately clear to me that these methods are overriding
    // some parent method. Otherwise, I might look at this and think, "What is
    // this for?" For other examples, it can be clearer why @Override is useful,
    // but get in to the habit of always adding @Override
    @Override
    public MathObject add(MathObject that) {
        // This is an example of something you could do
        if (that instanceof Constant) {
            return new Constant(c + ((Constant) that).c);
        }
        return that.add(this);
    }

    @Override
    public MathObject subtract(MathObject that) {
        // return that.subtract(this);
        // Some implementation here
    }

    @Override
    public double doubleValue() {
        return c;
    }
}

So then MathObject would be:

public interface MathObject {
    MathObject add(MathObject that);

    MathObject subtract(MathObject that);

    double doubleValue();
}
\$\endgroup\$
  • \$\begingroup\$ Thanks for the answer, never thought my spelling would be corrected when programming :) Could you explain what the @Override is good for, I always leave it out because javac deals with that itself. Also the thing that you are suggesting with the instanceof if statements was something I tried earlier but I kind of wanted to get Java itself to do that for me by seperating the methods, but I guess that's just not possible then. \$\endgroup\$ – S.Klumpers Mar 20 '16 at 17:01
  • \$\begingroup\$ Another little thing is that your MathObject add(MathObject that) tries to return a double rather than a Constant. \$\endgroup\$ – S.Klumpers Mar 20 '16 at 17:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.