[英]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.