Java构造函数重载歧义

时间:2013-06-07 07:29:38

标签: java constructor overloading

如何解决以下constructor overloading问题?这是一个面试问题,但我很想知道解决方案。

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;
    }
}

这里,编译器会给出错误,因为两个构造函数的参数类型相同。但从逻辑上讲,两者都不同。如何在不添加任何额外参数的情况下解决此问题?是否有专门针对此的设计模式?

4 个答案:

答案 0 :(得分: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;
      }
    }
}

用法:

Player player = Player.builder().name("John").internationalRank(522).build();

答案 1 :(得分:1)

你有各种各样的选择。

最简单的是添加像这样的工厂方法:

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;
  }

  ...
}

但是,这会留下一个未使用的变量,这个变量不是很好。更好的解决方案是添加PlayerType枚举:

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;
  }

  ...
}

哪个最好取决于确切的用例。

答案 2 :(得分:0)

只需反转其中一个构造函数的参数,你就可以了......我把这个答案认为是一个面试问题....也许面试官有这个想法......

 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;
        }
    }

答案 3 :(得分:0)

根据评论的建议,只需使用静态工厂方法。事实上,这个解决方案比这更进一步,并使用了一个构建器。您将注意到一个明显的优势:所有实例变量现在都是最终的。

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);
        }
    }
}

用法:

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