我有一个类似集合的接口,其中包含Collection
接口的大多数方法,但是存在一个与add
和contains
方法有关的问题,该问题仅涉及到从Collection
继承。
T
中类型为Collection
的元素实现一种copy
方法和一个setter,有时需要采用以下方式:
可以通过考虑一个采用字符串参数的集合来形象地看到这一点,但是如果添加了特定的字符串foo
,则截断的版本fo
或fo
加上另一个字符串{{ 1}}。
bar
问题在于,有时会插入多个元素,这与// Examples of the add() method internals
collection.add("foo"); // internally add("fo");
collection.add("foo"); // internally add("fo"); add("bar");
中的方法约定本身是好的,但是在插入之前更改元素有点脏。如果使用add
方法并插入了元素,它将不再copy
原始元素。
问题:不那么扩展contain
是正确的吗?还是在这里重新定义大多数收集方法是更好的选择?
答案 0 :(得分:2)
如果您的界面按照您的描述运行,则不应扩展Collection
,因为它确实违反了Collection
的{{1}}的约定,即:
确保此集合包含指定的元素
和
如果一个集合由于已经包含该元素以外的其他原因拒绝添加一个特定元素,则它必须引发一个异常(而不是返回false)。这样保留了不变,即在此调用返回之后,集合始终包含指定的元素。
如果add
实际上添加了“ fo”,则该合同被破坏。
如果您的界面扩展了collection.add("foo");
,则该界面的用户可以将您的界面的实例分配给Collection
变量,并期望其行为与Collection
界面中所述的一样。
答案 1 :(得分:1)
添加到@Eran的答案。
来自文档
If a collection refuses to add a particular element for any reason
other than that it already contains the element, it must throw
an exception (rather than returning false)
不要使用add方法。相反,您可以扩展Collection并添加遵循合同的新方法。
boolean addOrSplit(E e) {
if(contains(e)) {
//split e
//addOrSplit(e - Part1);
//addOrSplit(e - Part2);
} else {
add(e);
}
}
请确保您处理了递归结束条件,并在此实现中避免了无限循环。