Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/381.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 实现子类的泛型类_Java_Oop_Generics - Fatal编程技术网

Java 实现子类的泛型类

Java 实现子类的泛型类,java,oop,generics,Java,Oop,Generics,我创建了一个运动员班 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;

我创建了一个运动员班

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

此外,我创建了以下RunnerJumper类来创建另一种既能跑又能跳的运动员类型:

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();
    }
}
现在,我想创建一个团队类。团队应为跑步者或跳跃者团队(跑步者团队可包含跑步者和跳跃者,跳跃者团队可包含跳跃者和跳跃者) 所以我希望团队是通用的。。 此外,团队课程应该有类似“竞争”的方法( 例如:对于团队中的每个运动员: 跑或跳(取决于运动员的类型) )

我怎样才能达到这种行为

我试着这样做:

public class Team<C extends Athlete> {}
让IRunner和IJumper都扩展它。。 一开始这似乎很好:

public class Team<C extends Competitor> {}
公共类团队{}

但是我不明白如何在这种形式下实现Competite功能…

您可以创建两个团队课程,一个用于跑步者,另一个用于跳跃者,如下所示:

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();
        }
    }
}
公共接口团队{
公开无效竞争();
}
公共类TeamRunners实现团队{
私人名单;
私人跑步运动员名单;
公共团队(名单上的跑步者,名单上的运动员){
这个。跑步者=跑步者;
this.runnerJumpers=runnerJumpers;
}
@凌驾
公开竞逐(){
用于(跑步者:跑步者){
runner.run();
}
用于(RunnerJumper RunnerJumper:runnerJumpers){
runnerJumper.run();
runnerJumper.jump();
}
}
}
公共类TeamJumpers实现团队合作{
私人名单跳投者;
私人跑步运动员名单;
公共团队(名单跳投者,名单跳投者){
这个。跳线=跳线;
this.runnerJumpers=runnerJumpers;
}
@凌驾
公开竞逐(){
用于(跳线:跳线){
跳投;跳投;
}
用于(RunnerJumper RunnerJumper:runnerJumpers){
runnerJumper.run();
runnerJumper.jump();
}
}
}

不可能按你想象的方式去做

Java中的类型用于表示保证。对一段代码百分之百确定的事情。如果一段代码得到一只
,则100%保证它也是一只
和一只
动物

但是你不能像“它不是一只
鸭子
就是一只
水桶
”这样表达关系。您需要同时扩展同一个超类型,并确保该类型仅由这两个超类型扩展;一般来说,它需要多个继承和密封类型

并且不能表示将值与类型混合的关系,比如“如果
numberOfLegs==8
,那么类型就是
Octopus
”。我不知道该如何调用此操作所需的aparatus,但我认为类型脚本中的结构类型可以表示此类约束。我认为duck类型是一个先决条件

回到Java:如果有一组对象可以包含
Runner
s或
RunnerJumper
s,那么在Java的类型系统中唯一可以保证的是所有对象都是
Runner
s。任何泛型、继承等都不能改变这一点

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

  • 将跳跃/运行行为重构为一个单独的类,两个类都使用一个
    perform
    方法实现
    Action
    。然后用一个方法创建一个接口:
    getActions
    ,例如,调用
    Player
    。然后,您的
    团队
    可以迭代
    玩家
    s,获取每个玩家的操作,并在内部循环中调用他们的
    perform
    方法。
    getAction
    方法的实现甚至可以返回lambda的静态列表,这样您就可以从内部访问播放器的所有属性。此模式允许您保持可能操作的列表处于打开状态(引入新操作将不需要您重新编译或接触您的
    团队
    类)

  • 如果
    团队静态地知道可能的动作列表
    ,您可以使用
    访问者
    模式-让团队调用玩家的
    访问
    方法,玩家可以调用
    团队
    玩家跳跃(跳跃者j)
    玩家跳跃(跑步者r)


  • 或者,您可以使用该语言的其他机制:反射和投射(这也将使可能的操作列表保持静态)。

    到目前为止您尝试了什么?请将您的团队类的当前实现添加到您的问题中。谢谢,但我们的想法是创建一个由跑步者或跳跃者组成的专属团队(跑步者团队可以包含Runner和RunnerJumper),在这种情况下,只需使用两个团队类即可。我已经更新了我的答案。我将跑步者定义为列表跑步者不是更容易吗?它将确保跑步者是RunnerJumper的跑步者,对于
    Competite
    我可以迭代跑步者并让他们全部
    跑步
    否,您不能使用
    列表
    ,因为IRunner是一个接口,所以不会编译。
    public class Team<C extends Athlete> {}
    
    interface Competitor {}
    
    public class Team<C extends Competitor> {}
    
    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();
            }
        }
    }