简体   繁体   中英

Java - Return correct type from Generic method

I have the following class structure:

public class Team {
    ...
}

public class Event {

}

public abstract class Fixture<T extends Team> implements Event {
   ...
}

public abstract class Forecast<Event> {

}

public class MyPrediction<T extends Fixture<? extends Team>> extends Forecast<Fixture<? extends Team>>{

}

I am trying to model sports events of all kinds (ie a 'Fixture' is for a particular game between two participants play against each other, whereas another type of 'Event' may have many participants), along with predictions for the outcome of particular 'Events'. I have a generic method:

public <T> MyPrediction<Fixture<? extends Team>> getMyPrediction(Fixture<? extends Team> fixture) {

}

I want to be able to return a MyPrediction instance which has the generic type of the fixture argument, but I can't seem to do so. For example, if I do something like the following, then I get a compilation error:

SoccerFixture<EnglishSoccerTeams> soccerMatch = new ScoccerFixture<EnglishSoccerTeams>();
MyPrediction<SoccerFixture<EnglishSoccerTeams>> = getMyPrediction(soccerMatch);

I am willing to change my class structure to incorporate this feature. How can I do so?

Java's type system is not powerful enough to do directly what you propose, because of type erasure (the generic parameters are not available at runtime.

The usual solution is to create a separate EventFactory class, which you can then pass in to any method which needs to create a specific Event subtype instance.

Change the signature of getMyPrediction to

public <T extends Fixture<? extends Team>> MyPrediction<T> getMyPrediction(T fixture)

This tells the compiler that the fixture types in the argument and result are the same, allowing type-checking to pass.

Here is a complete example, with some other minor changes to get it to compile. It introduces the class Predictor to hold the getMyPrediction method and a doit method to show sample use:

public interface Team {
}

public interface Event {
}

public abstract class Fixture<T extends Team> implements Event {
}

public abstract class Forecast<T> {
}

public class MyPrediction<T extends Fixture<? extends Team>> extends
        Forecast<Fixture<? extends Team>> {
}

public class SoccerFixture<T extends SoccerTeam> extends Fixture<T> {
}

public class SoccerTeam implements Team {
}

public class EnglishSoccerTeam extends SoccerTeam {
}

public class Predictor {

    public <T extends Fixture<? extends Team>> MyPrediction<T> getMyPrediction(T fixture) {
        return new MyPrediction<T>();
    }

    public void doit() {
        SoccerFixture<EnglishSoccerTeam> soccerMatch = new SoccerFixture<EnglishSoccerTeam>();
        MyPrediction<SoccerFixture<EnglishSoccerTeam>> myPrediction = getMyPrediction(soccerMatch);
    }
}

As noted elsewhere, you might need to introduce one or more factory objects to perform meaningful work in the MyPrediction implementation.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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