Using Factory Method to Create Generics

155 views Asked by At

I have an abstract class (Candy) with a generic collection (Flavors). Candy has a factory method to produce concrete instances of itself. It also has methods to get an instance of the generic flavor appropriate to the concrete candy and to add the flavor to its collection.

I know the getter is working, because if I cast the flavor from the CandyStore, the methods unique to the concrete flavor work fine. But the very last line, the addFlavor(flavor), errs (Eclipse) on me. The error is: "The method addFlavor(capture#5-of ? extends IFlavor) in the type ICandy is not applicable for the arguments (IFlavor)." Can anyone explain what is going on?

Interface:

public interface ICandy <Flavor extends IFlavor> {
    public Flavor getFlavorForCandy();
    public void addFlavor(Flavor flavor);
}

Abstract Class:

public abstract class AbstractCandy<Flavor extends IFlavor> implements ICandy<Flavor> {
    public static ICandy<? extends IFlavor> buildCandy(String flavor){
        if(flavor.equals("Jolly Rancher")
            return new JolRanchCandy();
    }
    public Flavor getFlavorForCandy() {
        return (Flavor) new CandyFlavor();
    }
    public void addFlavor(Flavor flavor) {
        ... //implemented
    }
}

Concrete Class:

public class JolRanchCandy extends AbstractCandy<JolRanchFlavor> {
    ... //implemented
}

Used By:

public class CandyStore {
    private ICandy<? extends IFlavor> candy;
    private IFlavor flavor;
    public void createCandy() {
        candy = AbstractCandy.buildCandy("Jolly Rancher");
        flavor = candy.getFlavorForCandy(); //returns a JolRanchFlavor
        flavor.setName("Apple");            //etc for creating flavor
        candy.addFlavor(flavor);   //no luck
    }
}

Edit: For clarity, JolRanchFlavor extends CandyFlavor implements IJolRanchFlavor and CandyFlavor implements IFlavor.

1

There are 1 answers

4
John B On BEST ANSWER

Try this...

public <T extends IFlavor> void createCandy() {
    ICandy<T> candy= (ICandy<T>) AbstractCandy.buildCandy("Jolly Rancher");
    T flavor= candy.getFlavorForCandy(); 
    flavor.setName("Apple");            
    candy.addFlavor(flavor);  
}

The problem is the declaration of private ICandy<? extends IFlavor> candy. Since the type of the candy is unknown and therefore ? the compiler doesn't know exactly what kind of IFlavor addFlavor should take. You just need to define a generic holder for the IFlavor type so that it is preserved.