2014-09-29 54 views
1

我有一个接口,并实现它的类:不能通过的ArrayList <Impl>到方法采取的ArrayList <Interface>

public interface IFoo{ 
    Integer bar(); 
} 

public class Foo implements IFoo{ 
    @Override 
    public Integer bar(){ 
     return 42; 
    } 
} 

现在,在另一个类,我有一个函数,该函数的接口类型的ArrayList。

public class Something { 
    public static void function(ArrayList<IFoo> foos){ 
     //do something on foos 
    } 
} 

我想用这个函数foo的数组列表:

ArrayList<Foo> myFoos = new ArrayList<Foo>(); 
Something.function(myFoos);//can NOT do this 

有什么问题或者我该怎么办?

+2

稍微偏离主题,但为什么不'公共静态无效的功能(的IFoo FOOS ...)'? – Leon 2014-09-29 05:42:37

+0

我同意@Leon。编码到*界面*是一个好习惯。 – TheLostMind 2014-09-29 05:43:41

+0

你的界面名称是IFoo,而你生成的arraylist是Foo。但是在函数签名里面的Something类中你已经提到了正确的。 – 2014-09-29 05:43:49

回答

6

通用救援!

public static void function(ArrayList<? extends IFoo> foos){ 
    //do something on foos 
} 

现在函数采用任何种类的数组列表,其中所包含的类型是IFoo或从它衍生。

对于什么是值得的,使用最通用的类​​型也是一个好主意。你真的需要一个ArrayList,或者任何一种List吗?或者,也许任何种类的Collection

public static void function(List<? extends IFoo> foos); 
public static void function(Collection<? extends IFoo> foos); 

一个很好的经验法则是be conservative in what you send and liberal in what you accept from others。使用更通用的参数类型属于“自由”部分。

+0

谢谢。集合类型可能取决于。 – 2014-09-29 05:51:21

0

您可以通过使用泛型做到这一点:

public static void function(ArrayList<? extends IFoo> foos){ 

} 

所以你的问题很容易得到解决。

1

我会可能保留方法签名不变(除了接受List<IFoo>),促进接口类型的使用,如:

List<IFoo> myFoos = new ArrayList<IFoo>(); 

如果需要使用List<Foo> - 再次,与ArrayList! - 那么我可能会保留更简单的签名,并强制主叫方适当地进行投票,或者以其他方式提供表达式,将此类操作的责任留在呼叫地点。

(我主要是偏见子类型,并且更喜欢实用时回避这个covariance issue完全。)

+0

好吧,我会咬。你为什么偏向于分类? – 2014-09-29 06:01:16

+0

@JohnKugelman没有那么多的子类型作为继承子类型 - 关系:主要是对LSP(超出定义的接口契约)和具体类型的增加(并且太简单)的依赖性。 – user2864740 2014-09-29 06:12:04

+0

啊,知道了。我在那里同意你的意见。我认为你有一些针对通配符限定符的具体内容。这是一个奇怪的具体事情,恨。;-) – 2014-09-29 06:15:25

相关问题