繁体   English   中英

实现子类的通用 class

[英]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% 保证它也是BirdAnimal

但是你不能表达像“it's either a Duck or a Bucket ”这样的关系。 您将需要两者都扩展相同的超类型并确保该类型仅由这两者扩展; 一般来说,它需要多个 inheritance 和密封类型。

而且您不能表达将值与类型混合的关系,例如“如果numberOfLegs == 8 ,则类型为Octopus ”。 我不知道如何调用为此所需的工具,但我认为 Type Script 中的结构类型可以表达此类约束。 我认为鸭子打字是先决条件。

回到 Java:如果有一组对象可以包含Runner s 或RunnerJumper s,在 Java 的类型系统中你唯一可以保证的是所有对象都是Runner s。 没有 generics、inheritance 等可以改变它。

您可以使用多种模式中的一种来实现您的业务目标:

  1. 将跳跃/奔跑行为重构到单独的类中,两者都使用单个perform方法实现Action 然后用一个方法创建一个接口: getActions ,称为Player 然后,您的Team可以迭代Player ,为每个人获取动作并在内部循环中调用他们的perform方法。 getAction方法的实现甚至可以返回一个 static 的 lambda 列表,这样您就可以从内部访问您的玩家的所有属性。 此模式允许您将可能的操作列表保持打开状态(引入新操作不需要您重新编译或修改您的Team类)。

  2. 如果Team静态知道可能的操作列表,则可以使用Visitor模式 - 让 Team 调用玩家的visit方法,而玩家可以调用TeamplayerJumps(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.

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