繁体   English   中英

Java构造函数重载歧义

[英]Java constructor overloading ambiguity

如何解决以下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;
    }
}

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

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

您有多种选择。

最简单的方法是添加如下工厂方法:

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

  ...
}

最佳选择取决于确切的用例。

只需反转其中一个构造函数的参数,就可以了。...我回答这个问题是因为这是一个面试问题。...也许面试官已经想到了这一点...

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

正如评论所建议的那样,只需使用静态工厂方法即可。 实际上,此解决方案远不止于此,它使用了构建器。 您会注意到一个明显的优势:所有实例变量现在都是最终的。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM