[英]implement generic class of child classes
我创建了一个运动员 class。
public class Athlete {
private final int id;
private final String name;
private final Country sourceCountry;
public Athlete(int id, String name, Country sourceCountry){
this.id = id;
this.name = name;
this.sourceCountry = sourceCountry;
}
}
然后我创建了以下接口和子类:
public interface IJumper {
public double jump();
}
public interface IRunner {
public double run();
}
public class Runner extends Athlete implements IRunner {
public Runner(int id, String name, Country sourceCountryCode) {
super(id, name, sourceCountryCode);
}
@Override
public double run() {
return Math.random();
}
}
public class Jumper extends Athlete implements IJumper {
public Jumper(int id, String name, Country sourceCountry) {
super(id, name, sourceCountry);
}
@Override
public double jump() {
return Math.random();
}
}
此外,我创建了以下 RunnerJumper class 来创建另一种既能跑又能跳的运动员:
public class RunnerJumper extends Athlete implements IRunner, IJumper {
public RunnerJumper(int id, String name, Country sourceCountry) {
super(id, name, sourceCountry);
}
@Override
public double jump() {
return Math.random();
}
@Override
public double run() {
return Math.random();
}
}
现在,我想创建一个团队 class。该团队应该是跑步者或跳跃者团队(跑步者团队可以包含 Runner 和 RunnerJumper,而跳跃者团队可以包含 Jumper 和 RunnerJumper)所以我希望团队是通用的.. 另外团队 class 应该有像“竞争”这样的方法(比如:forEach Athlete of Team: run or jump (depends the type of athlete..))
我怎样才能实现这种行为?
我试图像这样创建它:
public class Team<C extends Athlete> {}
但是在这种形式的跑步者团队中不能包含 RunnerJumper ..我还尝试创建新的接口 Competitor:
interface Competitor {}
并让 IRunner 和 IJumper 扩展它..起初看起来不错:
public class Team<C extends Competitor> {}
但我不明白如何以这种形式实现竞争功能......
不可能按照你想象的那样去做。
类型 - Java - 用于表达保证。 对一段代码 100% 确定的事情。 如果一段代码得到Duck
,则 100% 保证它也是Bird
和Animal
。
但是你不能表达像“it's either a Duck
or a Bucket
”这样的关系。 您将需要两者都扩展相同的超类型并确保该类型仅由这两者扩展; 一般来说,它需要多个 inheritance 和密封类型。
而且您不能表达将值与类型混合的关系,例如“如果numberOfLegs == 8
,则类型为Octopus
”。 我不知道如何调用为此所需的工具,但我认为 Type Script 中的结构类型可以表达此类约束。 我认为鸭子打字是先决条件。
回到 Java:如果有一组对象可以包含Runner
s 或RunnerJumper
s,在 Java 的类型系统中你唯一可以保证的是所有对象都是Runner
s。 没有 generics、inheritance 等可以改变它。
您可以使用多种模式中的一种来实现您的业务目标:
将跳跃/奔跑行为重构到单独的类中,两者都使用单个perform
方法实现Action
。 然后用一个方法创建一个接口: getActions
,称为Player
。 然后,您的Team
可以迭代Player
,为每个人获取动作并在内部循环中调用他们的perform
方法。 getAction
方法的实现甚至可以返回一个 static 的 lambda 列表,这样您就可以从内部访问您的玩家的所有属性。 此模式允许您将可能的操作列表保持打开状态(引入新操作不需要您重新编译或修改您的Team
类)。
如果Team
静态知道可能的操作列表,则可以使用Visitor
模式 - 让 Team 调用玩家的visit
方法,而玩家可以调用Team
的playerJumps(Jumper j)
或playerRuns(Runner r)
。
或者您可以使用该语言的其他机制:反射和转换(这也会使可能的操作列表成为静态的)。
您可以做的是创建两个 Team 类,一个用于跑步者,一个用于跳跃者,如下所示:
public interface Team {
public void compete();
}
public class TeamRunners implements Team {
private List<Runner> runners;
private List<RunnerJumper> runnerJumpers;
public Team(List<Runner> runners, List<RunnerJumper> runnerJumpers) {
this.runners = runners;
this.runnerJumpers = runnerJumpers;
}
@Override
public void compete() {
for (Runner runner : runners) {
runner.run();
}
for (RunnerJumper runnerJumper : runnerJumpers) {
runnerJumper.run();
runnerJumper.jump();
}
}
}
public class TeamJumpers implements Team {
private List<Jumper> jumpers;
private List<RunnerJumper> runnerJumpers;
public Team(List<Jumper> jumpers, List<RunnerJumper> runnerJumpers) {
this.jumpers = jumpers;
this.runnerJumpers = runnerJumpers;
}
@Override
public void compete() {
for (Jumper jumper : jumpers) {
jumper.jump();
}
for (RunnerJumper runnerJumper : runnerJumpers) {
runnerJumper.run();
runnerJumper.jump();
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.