xav
xav

Reputation: 5618

Best practices to avoid Constructor clash due to same parameters types?

Although it occurs only on rare occasions, I sometimes need to have two Constructors having the same parameter types, of course with different parameters role for each Constructor. Here is an example:

public class MyClass {
    public MyClass(String title, String content) {
        // ...
    }

    public MyClass(String title, String link) {
        // ...
    }
}

I would be interested to know what you guys there do in this case?

  1. Swap parameters order for one Constructor when possible (well, not in my example)

  2. Give up the fight and call a setter after the Constructor

  3. Never happened since it should be managed by design, like polymorphism/inheritance

  4. Use a design pattern

  5. Add a dummy unused parameter to make them unique (no, really?)

  6. ...


EDIT: Not to self: I've just found an horrible thing in java.util.HashSet: (pretty surprising for a JDK class, even if it's package private)

/* ......
 * @param dummy  Ignored (distinguishes this constructor from other int, float constructor.)
 * ......
 */
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
    ...
}

Upvotes: 2

Views: 605

Answers (4)

robermann
robermann

Reputation: 1722

You could use a list of named factory methods, with a private constructor: the caller knows just the semantic of the methods, their implementation is hidden. Later, if you like, you can refactor the code without changing the caller.

I find this solution more suitable for your purpose, IMHO being the builder pattern an over-engineered solution (in your case).

public class MyClass {
    private MyClass(String title, String content, String link) {
        // ...
    }

    public static MyClass buildWithLink (String title, String link) {
        return new MyClass(title, null, link);
    }


    public static MyClass buildWithContent (String title, String content) {
        return new MyClass(title, content, null);
    }
}

Upvotes: 0

rgettman
rgettman

Reputation: 178293

Use the Builder Pattern. A nested class called Builder accepts settings, one setter method at a time, and a build() method returns the actual MyClass object.

public class MyClass {
   private String title;
   private String content;
   private String link;
   public static class Builder {
      private String title;
      private String content;
      private String link;

      public void setTitle(String title) { this.title = title; }
      public void setContent(String content) { this.content = content; }
      public void setLink(String link) { this.link = link; }
      public MyClass build() {
         return new MyClass(this);
      }
   }

   private MyClass(Builder builder) {
      // Validate here.
      if (builder.title == null)
         throw new IllegalArgumentException("Title is required!");
      this.title = builder.title;
      this.content = builder.content;
      this.link = builder.link;
   }
}

This way parameters won't get confused, and constructors don't multiply due to all the cases.

Upvotes: 4

Joseph
Joseph

Reputation: 599

You could maybe do something like this

public class Link{ /* constructor from string */ }
public class Content{ /* constructor from string */ }

And then overload the MyClass constructor with the Link and Content class seperately

Upvotes: 0

Chris Gerken
Chris Gerken

Reputation: 16392

In this case you can add static methods that answer an instance of the class. You can vary the name if you have like-typed arguments. In order to force the use of these methods you can have a single, no-arg constructor that's declared private.

Upvotes: 3

Related Questions