【问题标题】:Using Factory Method to Create Generics使用工厂方法创建泛型
【发布时间】:2014-11-24 14:28:43
【问题描述】:

我有一个带有通用集合(Flavors)的抽象类(Candy)。 Candy 有一个工厂方法来生成它自己的具体实例。它还具有获取适用于具体糖果的通用风味实例并将风味添加到其集合中的方法。

我知道 getter 正在工作,因为如果我从 CandyStore 投射风味,则具体风味特有的方法可以正常工作。但是最后一行,addFlavor(flavor), errs (Eclipse) 在我身上。错误是:“ICandy 类型中的方法 addFlavor(capture#5-of ? extends IFlavor) 不适用于参数 (IFlavor)。”谁能解释一下是怎么回事?

界面:

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

抽象类:

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
    }
}

具体类:

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

使用者:

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
    }
}

编辑:为清楚起见,JolRanchFlavor extends CandyFlavor implements IJolRanchFlavorCandyFlavor implements IFlavor

【问题讨论】:

  • 您已经声明了ICandy&lt;? extends IFlavor&gt; candy,并且此声明根本不允许添加任何Flavor。将其声明为 ICandy&lt;IFlavor&gt; candy 会更好。
  • @LuiggiMendoza 您的建议的问题是addFlavor 采用具体实例Flavor 而不是IFlavor
  • @JohnB 这种方法的问题是......另一个例子,List&lt;Number&gt; numbers = new ArrayList&lt;&gt;(); numbers.add(new Integer(5)); 编译和运行没有问题。
  • 但是NumberInteger匹配的接口。请注意addFlavor 采用Flavor,它不是接口而是类的泛型类型。比如ICandy &lt;T extends IFlavor&gt;中的T
  • [来自下面答案的相同评论] 这是因为您需要 JolRanchCandy 覆盖 getFlavorForCandy 以返回 JolRanchFlavor 的实例,因为默认实现返回 CandyFlavor

标签: java generics collections interface factory-method


【解决方案1】:

试试这个...

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

问题在于private ICandy&lt;? extends IFlavor&gt; candy 的声明。由于糖果的类型是未知的,因此? 编译器并不确切知道应该采用哪种类型的IFlavor addFlavor。您只需为 IFlavor 类型定义一个通用持有者,以便保留它。

【讨论】:

  • 感谢您的回答。这种方式可以同时将我所有的风味类型更改为 IFlavor。两者的问题是,当我尝试将风味降低到 JolRanchFlavor 以使用其独特的方法时,我得到“java.lang.ClassCastException:CandyFlavor 与 JolRanchFlavor 不兼容”。 (这可能需要一个新问题?)
  • 这是因为您需要JolRanchCandy 覆盖getFlavorForCandy 以返回JolRanchFlavor 的实例,因为默认实现返回CandyFlavor
  • 上面引出了一个问题,如果这个方法只能产生一个JolRanchCandy,那么candy的类型应该是JolRanchCandy。如果您要说,将方法设为通用是没有意义的,但是等一下,我知道这是什么。
  • 知道了。这是我希望通过泛型避免的,因为所有Candys 都返回一个特定于它们自己的CandyFlavor (IFlavor) 实现。 CandyStore 有一种硬编码的方法来区分要投射到什么(来自另一个系统,不是我可以控制的)。是的,还有更多不同的Candys,而不仅仅是一个。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-15
  • 1970-01-01
相关资源
最近更新 更多