我有一个抽象类(Candy)和一个泛型集合(Flavors)。 Candy具有一种工厂方法来产生其自身的具体实例。它还有一些方法可以获取适合具体糖果的通用风味实例并将其添加到其集合中。
我知道吸气剂正在工作,因为如果我从CandyStore投放风味,混凝土风味独特的方法效果很好。但是最后一行,addFlavor(flavor),对我来说是错误的(Eclipse)。错误是:\\\\"类型为ICandy的方法addFlavor(capture#5-of?扩展IFlavor)不适用于参数(IFlavor)。\\\\"任何人都可以解释发生了什么吗?
接口:
public interface ICandy {
public Flavor getFlavorForCandy();
public void addFlavor(Flavor flavor);
}
抽象类:
public abstract class AbstractCandy implements ICandy {
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 {
... //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 IJolRanchFlavor和CandyFlavor implements IFlavor。
您已经声明了ICandy extends IFlavor> candy,并且该声明根本不允许添加任何Flavor。最好将其声明为ICandy candy。
@LuiggiMendoza您的建议的问题是addFlavor采用一个具体实例Flavor而不是IFlavor。
@JohnB,这种方法的问题是...另一个示例,List numbers = new ArrayList<>(); numbers.add(new Integer(5));,它可以毫无问题地进行编译和运行。
但是Number是Integer匹配的接口。请注意,addFlavor采用Flavor,这不是接口,而是类的泛型类型。如ICandy 中的T
而且我猜JolRanchFlavor是实现Flavor接口或子类的类,因此当您使用ICandy时,代码也会编译。自己测试。
为此,我创建一个AbstractCandy。这样,addFlavor将仅接受JolRanchFlavor的实例,这是有意义的,因为它不应使用GoodAndPlentyFlavor。现在我强制转换为AbstractCandy,所以现在addFlavor将使用任何IFlavor。因此,我现在有权将GoodAndPlentyFlavor分配给应该只使用JolRanchFlavor的Candy。哦,那将是一个奇怪的世界。说"这是一些T的糖果,getFlavor给我一个T,我可以将T传递给addFlavor",这更有意义。
用I为接口名称加上前缀是一种糟糕的做法,它表明抽象有问题。
@JohnB正确执行语句时,CandyStore不会包含Candy糖果。曾经哦,那将是一个奇怪的世界。
为了清楚起见,JolRanchFlavor extends CandyFlavor implements IJolRanchFlavor和CandyFlavor implements IFlavor。将编辑为原始帖子。 @JarrodRoberson,我不希望完全没有接口,但是我的商店要求它们具有模拟类,因此我会尽力而为。
[下面的回答中有相同的评论。]感谢您的答复。从头到尾的通用类型都可以解决,也可以将所有flavor类型更改为IFlavor。两者的问题在于,当我然后尝试将flavor向下转换为JolRanchFlavor以使用其独特方法时,我得到" java.lang.ClassCastException:CandyFlavor与JolRanchFlavor \\不兼容"。 (这可能会提出一个新的问题?)
[与下面的回答相同的注释]这是因为您需要JolRanchCandy覆盖getFlavorForCandy才能返回JolRanchFlavor的实例,因为默认实现会返回CandyFlavor。
您能解释为什么它返回CandyFlavor吗?我看到它返回通用Flavor,即。
尝试一下...
public void createCandy() {
ICandy< T > candy= (ICandy< T >) AbstractCandy.buildCandy("Jolly Rancher");
T flavor= candy.getFlavorForCandy();
flavor.setName("Apple");
candy.addFlavor(flavor);
}
问题是private ICandy extends IFlavor> candy的声明。由于糖果的类型是未知的,因此?编译器并不确切知道应该使用哪种IFlavor addFlavor。您只需要为IFlavor类型定义一个通用持有人,以便保留它。
感谢你的回答。这种方法不仅可以将所有我的口味类型更改为IFlavor,而且还可以使用。两者的问题在于,当我尝试将风味转换为JolRanchFlavor以使用其独特方法时,会得到" java.lang.ClassCastException:CandyFlavor与JolRanchFlavor \\不兼容"。 (这可能会提出一个新的问题?)
这是因为您需要JolRanchCandy覆盖getFlavorForCandy才能返回JolRanchFlavor的实例,因为默认实现会返回CandyFlavor。
上面的问题是,如果此方法只能产生JolRanchCandy,则candy的类型应为JolRanchCandy。如果您要说的话,使该方法通用是没有意义的,但是等等,我知道这是什么。
得到它了。这就是我希望避免使用泛型的原因,因为所有Candy都返回特定于自己的CandyFlavor(IFlavor)实现。 CandyStore具有一种硬编码的方式,可以区分要强制转换的内容(与另一系统无关,我无法控制)。是的,还有更多不同的Candy,而不仅仅是一个。