Roh*_*bhu 5 java oop generics collections
在Java中,我们有以下类型的函数:
public Collection<String> removeNulls(Collection<String> input) {
List<String> output = new ArrayList<>();
// ...
return output;
}
Run Code Online (Sandbox Code Playgroud)
请注意,我没有以任何方式修改输入,因为很多时候我们碰巧使用ImmutableListList.更常见的是,我们尽可能地确保函数的不变性.但是,我在这里看到的一个陷阱是,我的所有方法都经常使用自己的实现Collection.如果有人使用我的库正在使用LinkedList或者a Set或者a SortedSet,"查找是O(1)"或"列表总是排序" 这样的假设会在我的列表中调用我的函数时中断:
Set<String> mySet = new SortedSet<>();
mySet.add(10);
mySet.add(9); // I know that my collection is now sorted
Collection<String> myFilteredSet = removeNulls(mySet); // It is no longer sorted
Set<String> mySet = Sets.newSortedSet(myFilteredSet); // Have to sort it again
Run Code Online (Sandbox Code Playgroud)
在a的情况下LinkedList,这变得更加微妙,如果我的函数返回a List,那么我将继续使用该列表.它不会有任何编译时错误,我也不会看到问题.在前一种情况下,问题至少是可见的,因为我仍然必须将返回的Collection(或List)转换为Set,我知道是什么.问题只会在以后出现,如果有一些重要的处理依赖于LinkedList使用.一种理想的方式(但并不意味着"推荐")将是:
public List<String> removeNulls(List<String> input) {
List<String> output = (List<String>)input.getClass().newInstance();
// ...
return output;
}
Run Code Online (Sandbox Code Playgroud)
这样,我确保至少使用相同的类型实现.在您看来,该问题的解决方案是什么?
编辑
只是为了澄清一点,我实际上没有removeNulls方法,这不是我想要的.这个问题与现实生活中的问题无关,但更多的是"需要考虑的事情".换句话说,我的问题是,鉴于你给我一个集合,我必须返回另一个集合,它以某种方式从它派生而不修改输入,我如何确保我的输出集合遵守合同(或具体来说,输入集合的实现)?
我想,您想要的是使用操作修改 Collection 接口withoutNulls,并相应地实现它,但由于您无法向现有集合类“添加”新方法,所以您运气不好。但是,由于您经常使用自己的集合实现,也许您可以扩展您的接口并提供一些方法将常规集合类转换为您自己的集合类。
像这样的东西:
public interface BetterCollection<E> extends Collection<E> {
BetterCollection<E> withoutNulls();
}
public class BetterLinkedList<E> extends LinkedList<E> implements BetterCollection<E> {
public BetterLinkedList() {}
public BetterLinkedList(LinkedList<E> input) {
super(input);
}
@Override
public BetterCollection<E> withoutNulls() {
BetterCollection<E> result = new BetterLinkedList<E>();
...
return result;
}
}
Run Code Online (Sandbox Code Playgroud)
我认为在 C# 中可以使用扩展方法,但是在实现上受到一些限制(例如,您无法访问私有字段,并且我不确定它们是否可以是虚拟的)。
Java 中的另一个解决方案是重载方法并让它们接受不同的集合类型,例如removeNulls(LinkedList<String>)or removeNulls(SortedSet<String>),但它显然也有其缺点。