[英]How to subclass Guava's ImmutableList?
当我尝试实现自己的ImmutableList
(实际上是委派给基础列表的包装器)时,出现以下编译器错误:
ImmutableListWrapper is not abstract and does not override abstract method isPartialView() in com.google.common.collect.ImmutableCollection
但是实际上,重写isPartialView()
似乎是不可能的,因为它受包保护,并且我想在自己的包中声明包装器。
为什么我不简单地扩展ImmutableCollection
? 因为我希望ImmutableList.copyOf()
返回我的实例,而不需要进行防御性复制。
我能想到的唯一方法是在guava的包中声明一个子类,该子类将isPartialView()
从受保护的包更改为公共的,然后由我的包装程序对其进行扩展。 有没有更清洁的方法?
我正在尝试通过创建一个包装程序来修复https://github.com/google/guava/issues/2029 ,该包装程序将委派给除spliterator()
以外的所有方法的基础ImmutableList,它将被覆盖。
我正在假设用户可以定义类型为ImmutableList
变量,并希望包装器可以直接替换(即,实现List
不足,他们期望得到ImmutableList
)。
如果您想要自己的不可变列表,但又不想实现它,则只需使用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;
}
}
如果您想要的行为不同于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*
实现任何东西; 你只是在脚上开枪。
如果您有合法的用例,请提出功能请求并描述您的需求,也许它将被合并。 否则,只需将包装器写入其他程序包中,然后提供您自己的方法和保证即可。 例如,没有什么强迫您使用ImmutableList.copyOf()
。 如果需要其他行为,只需编写自己的方法。
进一步研究,似乎此限制是设计使然:
引用http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/ImmutableList.html :
注意 :尽管此类不是最终的,但由于没有公共或受保护的构造函数,因此无法将其子类化。 因此,保证了这种类型的实例是不可变的。
所以看来我需要在guava包中创建包装器。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.