2

I try to reuse my constructor like this:

    public final long x;
    public final long y;
    public final int level;
    private final int hash;
    public final Point tileCenter;

    public TileCoordinate(long x, long y, int level) {
        this.x = x;
        this.y = y;
        this.level = level;
        this.hash = Objects.hash(x, y, level);
        this.tileCenter = getTileCenter();
    }

    public TileCoordinate(String key) {
        String[] bits = key.split("-");
//      this.level = Integer.parseInt(bits[0]);
//      this.x = Long.parseLong(bits[1]);
//      this.y = Long.parseLong(bits[2]);
        this(Long.parseInt(bits[0]),Long.parseLong(bits[1]),Integer.parseLong(bits[2]));
        this.hash = Objects.hash(x, y, level);
        this.tileCenter = getTileCenter();
    }

Since I don't want to write this(Integer.parseInt(key.split("-")[0]),Long.parseLong(key.split("-")[1]),Long.parseLong(key.split("-")));, what are my options?

6
  • 1
    Would you mind clarifying what since i don't want to repeat key.split for every parameter means? You only have one parameter correct? Commented Jan 10, 2019 at 21:14
  • no, i mean i dont want to write this(Integer.parseInt(key.split("-")[0]),Long.parseLong(key.split("-")[1]),Long.parseLong(key.split("-"))); Commented Jan 10, 2019 at 21:14
  • Is that because the call to this must be the first statement in a constructor, if it exists? Commented Jan 10, 2019 at 21:16
  • yes thats the problem Commented Jan 10, 2019 at 21:16
  • How about a static factory method instead? Commented Jan 10, 2019 at 21:17

3 Answers 3

4

It looks like you're only doing this line String[] bits = key.split("-"); to avoid having to call it 3 times in the deferred constructor call to this(), which, if it exists, must be the first statement in a constructor.

Instead of delegating to a constructor for the actual field assignment, delegate to a private method that handles the field assignments.

public TileCoordinate(String key) {
    String[] bits = key.split("-");
    init(Long.parseInt(bits[0]),Long.parseLong(bits[1]),Integer.parseInt(bits[2]));
    this.hash = Objects.hash(x, y, level);
    this.tileCenter = getTileCenter();
}

private void init(long x, long y, int level) {
    // assign to fields here
}

Make sure it's private so it can't be overridden, where leaking this would become a problem.

You may also want to verify that bits has 3 elements before continuing.

Sign up to request clarification or add additional context in comments.

2 Comments

But the fields are final, forgot to tell this
Well now that you've revealed that your fields are final, this won't work. In that case, a factory method would be the way to go.
3

The call to this() or super() must be the first statement in the constructor. One way to fix it would be to convert the second constructor into a Factory Method:

public static TileCoordinate parseTitleCoordinate(String key) {
  String[] bits = key.split("-");
  long x = Long.parseLong(bits[0]);
  long y = Long.parseLong(bits[1]);
  long level = Long.parseLong(bits[2]);
  return new TitleCoordinate(x, y, level);
}

This would allow to keep the fields final.

1 Comment

Why super() is needed?
0

Could overload an init method:

  public TileCoordinate(long x, long y, int level) {
      init(x, y, level);
  }

  public TileCoordinate(String key) {
      init(key);
  }

  private void init(String key) { 
      String[] bits = key.split("-");
      init(Long.parseLong(bits[0]),
           Long.parseLong(bits[1]),
           Integer.parseInt(bits[2]));
  }

  private void init(long x, long y, int level) { 
      this.setX(x);
      this.setY(y);
      this.setLevel(level);
  }

This maintains single-responsibility. Only the 2nd init method is calling the setters, the rest are delegating.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.