Friday, February 24, 2012

How do I call a method of a generic type in a collection which is guaranteed to exist?


I have been using generics for sometime, but only in a simple straightforward fashion.



Now I would like to do this, I have been reading and trying many things, such as using interfaces and wildcards but with no success. I would like to learn if there is a valid way to achieve this with Java generics, or if I have misunderstood they way in which generics should be used.



Lets say I want to make a generic collection class, an ArrayList, and I want to create such arraylists for various differing types BUT IMPORTANTLY differing types which are ASSURED to implement a certain method. I would then like to be able to call that method from within my generic arraylist.



The following code is very simplistic, and clearly will not work, I know that. I have tried plenty more sophisticated ideas than this, however I include the following code just to sum up what I am trying to do, and to provide an example for answers.



See the line of code in DemonstrateProblem()...I would like to be able to call that on the understanding that I will only ever use types in TestContainer which implement the method StartGame()




public class TestContainer<T> extends ArrayList<T> {
public void DemonstrateProblem() {
// assumes we have populated the collection with 5+ objects...
// the line of code below is ultimately what I would like to acheive
this.get(4).StartGame(); // <-- my goal!
}
}

public abstract class Game () {
public abstract void StartGame() {}
public abstract void EndGame() {}
}

public class HockeyGame extends Game {
// ... overrides here
}

public class BaseballGame extends Game {
// ... overrides here
}

public class BasketballGame extends Game {
// ... overrides here
}

2 comments:

  1. What you want to do is restrict the types that your genericized class will accept to only those that implement the behavior you are expecting. You can do this by:


    Implementing an interface with your expected behavior
    Restricting the bounds of your generic type to that interface.


    Illustrated in an enhanced version of your pseudocode:

    public interface Game {
    public void StartGame();
    }

    public class TestContainer<T extends Game> extends ArrayList<T> {
    public void DemonstrateProblem() {
    // assumes we have populated the collection with 5+ objects...
    // the line of code below is ultimately what I would like to acheive
    this.get(4).StartGame(); // <-- my goal!
    }
    }

    ReplyDelete
  2. You do not need to keep your container generic on T: you can instantiate an existing generic container on Game, like this:

    public class TestContainer extends ArrayList<Game> {
    public void DemonstrateProblem() {
    this.get(4).StartGame(); // <-- should work
    }
    }

    ReplyDelete