首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从抽象集合生成抽象集合

从抽象集合生成抽象集合
EN

Stack Overflow用户
提问于 2011-11-30 20:31:26
回答 7查看 456关注 0票数 4

这个问题已经困扰我一段时间了。抽象地说,不管使用哪种语言,通常都会出现这样的情况:

代码语言:javascript
复制
Collection method(Collection c) {
    // select some elements from c based on some filter 
    // and return a new collection
}

现在,在这种情况下,Collection是一些抽象类(就像C#中的IList或Java中的List ),它有几个实现。我一直在想,生成抽象集合的正确过程到底是什么?

是否可以在方法中创建一个具体的集合并返回它?像这样:

代码语言:javascript
复制
Collection method(Collection c) {
   Collection cc = new ConcreteCollection();
   // select some elements from c based on some filter 
   return cc;
}

这当然会对结果集合施加约束,并会产生问题,以防出于某种原因,我们希望将方法的结果强制转换为与方法内部使用的集合不同的具体集合。

或者,使用反射来确定c的实际具体类型,并创建该类的实例:

代码语言:javascript
复制
Collection method(Collection c) {
   Collection cc = c.getClass().newInstance();
   // select some elements from c based on some filter 
   return cc;
}

出于某种原因,这对我来说似乎不是很“优雅”。我非常感谢在这件事上的一些见解。

EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2011-11-30 20:42:22

(以java为例)。返回集合(接口)而不是具体类型(如ArrayList)的原因是,您告诉用户他们不应该关心实际使用的具体类型是什么。这让您可以自由地为您的库/api选择合适的类型。

如果您要强制执行特定的具体类,则应该返回该具体类,而不是接口。

所以,他们不应该将你的返回类型转换为Collection以外的任何类型。参见When should I return the Interface and when the concrete class?

票数 4
EN

Stack Overflow用户

发布于 2011-11-30 22:53:16

在Java语言中,实际上在java.util.Collections类中有一些很好的示例来说明如何做到这一点。键方法接受两个集合,"src“和"dest”,而不是接受一个Collection并返回一个Collection。例如,查看copy方法的签名:

代码语言:javascript
复制
public static <T> void copy(List<? super T> dest, List<? extends T> src)

这将实例化目的地列表的责任交给了调用者。

我认为当您想要创建一个作用于src Collection的方法并将结果放入一个destination Collection (而不是List)时,您可以做同样的事情。

我同意Matthew Farwell的回答,您可能只想返回接口并利用它,但是当您确实需要使用特定的实现类时,您可以像Collections类一样完成它。

票数 3
EN

Stack Overflow用户

发布于 2011-11-30 20:57:53

您可以采用的一种方法是创建一个Collection实现,将调用委托给原始Collection。这会将可能代价高昂的筛选大型Collection的操作推迟到您需要显式读取元素时进行。它还可以节省内存。

示例

代码语言:javascript
复制
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);
  }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8325993

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档