如何继承Guava的ImmutableList?

时间:2015-07-28 03:09:45

标签: java guava

当我尝试实现自己的ImmutableList(实际上是委托给基础列表的包装器)时,我得到以下编译器错误:

ImmutableListWrapper is not abstract and does not override abstract method isPartialView() in com.google.common.collect.ImmutableCollection

但事实上,似乎无法覆盖isPartialView(),因为它受到包保护,我想在我自己的包中声明包装器。

为什么我不延伸ImmutableCollection?因为我希望ImmutableList.copyOf()在不制作防御性副本的情况下返回我的实例。

我能想到的唯一方法是在guava的包中声明一个子类,它将isPartialView()从包保护更改为public,然后让我的包装器扩展它。 有更清洁的方式吗?

我想做什么

我试图通过创建一个包装器来修复https://github.com/google/guava/issues/2029,该包装器将委托给除spliterator()之外的所有方法的基础ImmutableList,它将覆盖它。

我的工作假设是用户可以定义ImmutableList类型的变量,并期望包装器成为替代品(即它不足以实现List,他们期待ImmutableList)。

3 个答案:

答案 0 :(得分:3)

如果您想要自己的不可变列表但又不想实现它,请使用ForwardingList。另外,要实际制作副本,请使用Iterator作为copyOf的参数。这是一个解决方案,应该满足您在问题和答案中描述的所有要求。

public final class MyVeryOwnImmutableList<T> extends ForwardingList<T> {
  public static <T> MyVeryOwnImmutableList<T> copyOf(List<T> list) {
    // Iterator forces a real copy. List or Iterable doesn't.
    return new MyVeryOwnImmutableList<T>(list.iterator());
  }

  private final ImmutableList<T> delegate;

  private MyVeryOwnImmutableList(Iterator<T> it) {
    this.delegate = ImmutableList.copyOf(it);
  }

  @Override
  protected List<T> delegate()
  {
    return delegate;
  }
}

答案 1 :(得分:2)

如果您想要与ImmutableList.copyOf()提供的行为不同,只需定义其他方法,例如

public class MyList {
  public static List<E> copyOf(Iterable<E> iter) {
    if (iter instanceof MyList) {
      return (List<E>)iter;
    return ImmutableList.copyOf(iter);
  }
}

Guava的不可变类提供了许多保证,并对其实现如何工作做出了许多假设。如果其他作者可以实现他们自己的扩展Guava不可变类型的类,那么这些将被违反。即使您正确地实现了您的类以使用这些保证和假设,也没有什么能阻止这些实现细节在将来的版本中更改,此时您的代码可能会以奇怪或不可检测的方式中断。

请不要试图在Guava的Imutable* heirarchy中实施任何东西;你只是在脚下射击自己。

如果您有合法的用例,请提交feature request并描述您需要的内容,也许它会被合并。否则,只需将包装器写在不同的包中,并提供自己的方法和保证。例如,没有什么可以迫使你使用ImmutableList.copyOf()。如果您需要不同的行为,只需编写自己的方法。

答案 2 :(得分:-2)

在进一步挖掘时,看起来这个限制是设计的:

引用 http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/ImmutableList.html

  

注意:虽然此类不是最终的,但它不能被子类化,因为它没有公共或受保护的构造函数。因此,这种类型的实例保证是不可变的。

所以我似乎需要在guava包中创建我的包装器。