0

I want to write add(), subtract(), and equals() methods for my simple objects, allowing for nulls in fields. I end up using python to generate boilerplate code, and this tells me I am doing something wrong. What is the DRYer way to write a class like this?

package com.blicket.parser;

/**
 * Created by steve on 8/22/16.
 */
public class Foo {
    public Integer bar;
    public Integer baz;
    public Integer qux;

    public boolean equals(Foo b){
        if(
            (this.bar == b.bar || this.bar.equals(b.bar) &&
            (this.baz == b.baz || this.baz.equals(b.baz) &&
            (this.qux == b.qux || this.qux.equals(b.qux) &&
        ){
         return true;
        } else {
            return false;
        }
    }

    public Foo add(Foo a, Foo b){
        Foo c = new Foo();
        c.bar = a.bar + b.bar;
        c.baz = a.baz + b.baz;
        c.qux = a.qux + b.qux;
        return c;
    }
}

EDIT: I was using == for null checks, but it is redundant. Don't do that, reader. I am leaving the bad code sample to ensure the comments make sense.

EDIT 2: Trying to strip out the == checks, if bar, baz, or qux is null, doesn't

public boolean equals(Foo b){
    if(
        this.bar.equals(b.bar) &&
        this.baz.equals(b.baz) &&
        this.qux.equals(b.wux)
    ){
     return true;
    } else {
        return false;
    }
}

throw NullPointerException?

EDIT 3 Electric Jubilee: Looks like the right answer is

public boolean equals(Foo b){
    return Objects.equals(this.bar, b.bar) &&
        Objects.equals(this.baz, b.baz) && 
        Objects.equals(this.qux, b.qux);
}
bwarren2
  • 1,347
  • 1
  • 18
  • 36
  • 1
    Short of code generation, byte-code generation, or runtime reflection, there it's not obvious there's a way to do this for the general case. – Oliver Charlesworth Aug 22 '16 at 15:03
  • @azurefrog: I was fiddling with triple-tick block formatting, and failing to get the result I wanted. I see that you indented everything; is this the only way to get your better result? Ideas on why triple-tick failed? – bwarren2 Aug 22 '16 at 15:03
  • 2
    [Don't use `==` to compare `Integer` objects.](http://stackoverflow.com/questions/3637936/java-integer-equals-vs) – azurefrog Aug 22 '16 at 15:04
  • Here's the [markdown editing help page](http://stackoverflow.com/editing-help). I'm not familiar with this triple-tick. Perhaps it's not supported by SO's formatter? – azurefrog Aug 22 '16 at 15:04
  • Can you store your bar, baz, qux in an array of integers instead? Then your code can be turned into loops. – assylias Aug 22 '16 at 15:06
  • @azurefrog: Looks like it is github flavored markdown only: https://help.github.com/articles/creating-and-highlighting-code-blocks/#fenced-code-blocks – bwarren2 Aug 22 '16 at 15:06
  • do you know project lombok? https://projectlombok.org/ – David Pérez Cabrera Aug 22 '16 at 15:07
  • @assylias I want specifically named fields to uphold a JSON format on export with Jackson. I guess I could store everything in arrays until final formatting, but that seems messy. – bwarren2 Aug 22 '16 at 15:08
  • 1
    @bwarren2 instead of your complicated equals, you can simply `return Objects.equals(this.bar, b.bar) && Objects.equals(this.baz, b.baz) && Objects.equals(this.qux, b.qux);`. That will handle the null case for you. – assylias Aug 22 '16 at 15:56
  • @assylias: Oh that's great. You win the prize. – bwarren2 Aug 22 '16 at 16:03

1 Answers1

-3

You should try Groovy, which has support for + and - with overloading operations:

http://groovy-lang.org/operators.html Chapter 10. Operator overloading

https://www.ibm.com/developerworks/library/j-pg10255/

So instead of public boolean add(Foo a, Foo b) you write:

def plus(Foo foo){
  this.bar+=foo.bar
  this.baz+=foo.baz
  this.qux*=foo.qux
}

And then you use it as:

  Foo a = ...
  Foo b = ...
  Foo c = a + b;

So the right answer to your question is to expand the language an not to generate boilerplate code.

Tobias Otto
  • 1,634
  • 13
  • 20