0

How to solve the following constructor overloading problem? This is an interview question but I am curious to know the solution.

class Player
{
    int nationalRank;
    int internationalRank;
    String name;

    Player(String name, int nationalRank)
    {
        this.name= name;
        this.nationalRank = nationalRank;
        this.internationalRank=0;
    }

    Player(String name, int internationalRank)
    {
        this.name= name;
        this.nationalRank = 0;
        this.internationalRank=internationalRank;
    }
}

Here, the compiler will give an error because argument types are same for both constructor. But logically they both are different. How can I solve this problem without adding any extra arguments? Is there any design pattern specifically for this?

9
  • 2
    How about a static factory method with a meaningful name for each option? Commented Jun 7, 2013 at 7:31
  • They have the same prototype, without changing arguments I can't see how you could do this, what are you allowed to do? Make subclasses maybe? Commented Jun 7, 2013 at 7:31
  • @Djon Yeah, I think I am allowed to make subclasses. Any solution would be preferred. Commented Jun 7, 2013 at 7:33
  • 1
    One simple but ambiguous solution would be to change the order of parameters (int,String) and (String,int). Commented Jun 7, 2013 at 7:34
  • @TheNewIdiot Yeah, but I don't think this solution will be preferred on a real project. Commented Jun 7, 2013 at 7:35

4 Answers 4

3
class Player
{
    int nationalRank;
    int internationalRank;
    String name;

    private Player(){}

    public static Builder builder() 
    {
       return new Builder();
    }

    public static class Builder
    {
      int nationalRank = -1;
      int internationalRank = -1;
      String name;

      public Builder nationalRank(int nationalRank)
      {
        this.nationalRank = nationalRank;
        return this;
      }

      public Builder internationalRank(int internationalRank)
      {
        this.internationalRank = internationalRank;
        return this;
      }

      public Builder name(String name)
      {
        this.name = name;
        return this;
      }

      public Player build()
      {
        if (nationalRank == -1 && internationalRank = -1)
          throw new IllegalStateException("both ranks haven't been initialized");
        if (null == name)
          throw new IllegalStateException("name hasn't been initialized");
        Player result = new Player();
        result.nationalRank = this.nationalRank;
        result.internationalRank = this.internationalRank;
        result.name = this.name;
        return result;
      }
    }
}

Usage:

Player player = Player.builder().name("John").internationalRank(522).build();
Sign up to request clarification or add additional context in comments.

2 Comments

+1 interesting. how it's pattern called? i think it's not just factory pattern.
I'd say it's a flavor of a Builder Design Pattern: javarevisited.blogspot.ch/2012/06/…
1

You've got various options.

The simplest is to add factory methods like this:

public class Player
{
  private int nationalRank;
  private int internationalRank;
  private String name;

  private Player()
  {
  }

  public static Player newNationalPlayer(String name, int nationalRank)
  {
    Player nationalPlayer = new Player();

    nationalPlayer.name= name;
    nationalPlayer.nationalRank = nationalRank;
    nationalPlayer.internationalRank = 0;

    return nationalPlayer;
  }

  public static Player newInternationalPlayer(String name, int internationalRank)
  {
    Player internationalPlayer = new Player();

    internationalPlayer.name= name;
    internationalPlayer.nationalRank = 0;
    internationalPlayer.internationalRank = internationalRank;

    return internationalPlayer;
  }

  ...
}

However, this leaves an unused variable which isn't very nice. A better solution would be to add a PlayerType enum:

public enum PlayerType
{
  NATIONAL,
  INTERNATIONAL
}

public class Player
{
  private int rank;
  private String name;
  private PlayerType type;

  public Player(String name, PlayerType type, int rank)
  {
    this.name= name;
    this.type = type;
    this.rank = rank;
  }

  ...
}

Which is best is down to the exact use case.

Comments

0

Just reverse the parameters of one of the constructors and you are good to go.... I made this answer thinking that it's an interview question....perhaps the interviewer has this in mind...

 class Player
    {
        int nationalRank;
        int internationalRank;
        String name;

        Player(String name, int nationalRank)
        {
            this.name= name;
            this.nationalRank = nationalRank;
            this.internationalRank=0;
        }

        Player( int internationalRank,String name)
        {
            this.name= name;
            this.nationalRank = 0;
            this.internationalRank=internationalRank;
        }
    }

4 Comments

Oh I see what you did there.
Thats a good hack. But maybe can I get more generalized solution
Yes but he answered the question and I really did not see it coming.
@SamDufel but in interviews they check if the person has this kind of ability.....also...and that's an interview question...not a real project....if it's a real project we are not as restricted
0

As suggested by a comment, just use static factory methods. In fact, this solution goes further than that and uses a builder. You will note a clear advantage: all instance variables are now final.

public class Player
{
    private final String name;
    private final int nationalRank;
    private final int internationalRank;

    // Constructor becomes private
    private Player(final Builder builder)
    {
        name = builder.name;
        nationalRank = builder.nationalRank;
        internationalRank = builder.internationalRank;
    }

    public static Builder withName(final String name)
    {
        return new Builder(name);
    }

    // Inner builder class
    public static class Builder
    {
        private final String name;
        private int nationalRank;
        private int internationalRank;

        private Builder(final String name)
        {
            this.name = name;
        }

        public Builder withNationalRank(int rank)
        {
            nationalRank = rank;
            return this;
        }

        public Builder withInternationalRank(int rank)
        {
            internationationalRank = rank;
            return this;
        }

        public Player build()
        {
            return new Player(this);
        }
    }
}

Usage:

Player player1 = Player.withName("foo").withNationalRank(1).build();
// etc

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.