当我尝试实现自己的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
)。
答案 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包中创建我的包装器。