这个问题已经困扰我一段时间了。抽象地说,不管使用哪种语言,通常都会出现这样的情况:
Collection method(Collection c) {
// select some elements from c based on some filter
// and return a new collection
}现在,在这种情况下,Collection是一些抽象类(就像C#中的IList或Java中的List ),它有几个实现。我一直在想,生成抽象集合的正确过程到底是什么?
是否可以在方法中创建一个具体的集合并返回它?像这样:
Collection method(Collection c) {
Collection cc = new ConcreteCollection();
// select some elements from c based on some filter
return cc;
}这当然会对结果集合施加约束,并会产生问题,以防出于某种原因,我们希望将方法的结果强制转换为与方法内部使用的集合不同的具体集合。
或者,使用反射来确定c的实际具体类型,并创建该类的实例:
Collection method(Collection c) {
Collection cc = c.getClass().newInstance();
// select some elements from c based on some filter
return cc;
}出于某种原因,这对我来说似乎不是很“优雅”。我非常感谢在这件事上的一些见解。
发布于 2011-11-30 20:42:22
(以java为例)。返回集合(接口)而不是具体类型(如ArrayList)的原因是,您告诉用户他们不应该关心实际使用的具体类型是什么。这让您可以自由地为您的库/api选择合适的类型。
如果您要强制执行特定的具体类,则应该返回该具体类,而不是接口。
所以,他们不应该将你的返回类型转换为Collection以外的任何类型。参见When should I return the Interface and when the concrete class?。
发布于 2011-11-30 22:53:16
在Java语言中,实际上在java.util.Collections类中有一些很好的示例来说明如何做到这一点。键方法接受两个集合,"src“和"dest”,而不是接受一个Collection并返回一个Collection。例如,查看copy方法的签名:
public static <T> void copy(List<? super T> dest, List<? extends T> src)这将实例化目的地列表的责任交给了调用者。
我认为当您想要创建一个作用于src Collection的方法并将结果放入一个destination Collection (而不是List)时,您可以做同样的事情。
我同意Matthew Farwell的回答,您可能只想返回接口并利用它,但是当您确实需要使用特定的实现类时,您可以像Collections类一样完成它。
发布于 2011-11-30 20:57:53
您可以采用的一种方法是创建一个Collection实现,将调用委托给原始Collection。这会将可能代价高昂的筛选大型Collection的操作推迟到您需要显式读取元素时进行。它还可以节省内存。
示例
public interface Filter<T> {
boolean include(T t);
}
public class FilterCollection<T> implements Collection<T> {
private final Collection<T> orig;
private final Filter<T> filter;
public FilterCollection(Collection<T> orig, Filter<T> filter) {
this.orig = orig;
this.filter = filter;
}
public int size() {
int sz = 0;
for (T t : orig) {
if (filter.include(t)) {
++sz;
}
}
return sz;
}
public boolean contains(Object o) {
return o instanceof T && filter.include((T) o) && orig.contains(o);
}
public boolean add(T t) {
if (!filter.include(t)) {
throw new IllegalArgumentException("Element lies outside filter bounds.");
}
orig.add(t);
}
}https://stackoverflow.com/questions/8325993
复制相似问题