gpt4 book ai didi

java - 扩展List增加字段是否合适

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:41:50 25 4
gpt4 key购买 nike

问题是为 List 设计的,但很容易应用于 java 集合框架中的其他问题。

例如,我会说创建一个新的 List 子类型来存储诸如加法计数器之类的东西当然是合适的,因为它是列表操作的组成部分并且不会改变它“是一个列表”。像这样:

public class ChangeTrackingList<E> extends ArrayList<E> {
private int changeCount;
...
@Override public boolean add(E e) {
changeCount++;
return super.add(e);
}
// other methods likewise overridden as appropriate to track change counter
}

但是,如何添加超出列表 ADT 知识的附加功能,例如存储与列表元素关联的任意数据?当然,假设在添加和删除元素时关联的数据得到了适当的管理。像这样:

public class PayloadList<E> extends ArrayList<E> {
private Object[] payload;
...
public void setData(int index, Object data) {
... // manage 'payload' array
payload[index] = data;
}
public Object getData(int index) {
... // manage 'payload' array, error handling, etc.
return payload[index];
}
}

在这种情况下,我通过不仅添加额外的功能(行为)而且还添加额外的状态来改变它“只是一个列表”。当然是类型规范和继承的部分目的,但是是否存在对 Java 集合类型的隐式限制(禁忌、弃用、不良实践等)以特殊对待它们?

例如,当将此 PayloadList 引用为 java.util.List 时,将正常进行变异和迭代并忽略负载。当涉及到不希望 List 携带要维护的额外数据的持久性或复制时,这是有问题的。我见过很多地方接受一个对象,检查它是否“是一个列表”,然后简单地将它视为 java.util.List。他们是否应该允许任意应用程序贡献来管理特定的具体子类型?

由于此实现会在实例切片(忽略子类型字段)中不断产生问题,以这种方式扩展集合并在有额外数据需要管理时始终使用组合是否是个坏主意?或者它是持久性或复制的工作,以说明包括附加字段在内的所有具体子类型?

最佳答案

这纯粹是个人意见,但我个人建议不要扩展像 ArrayList 这样的类。在几乎所有情况下,都倾向于组合。

甚至你的ChangeTrackingList相当狡猾。什么

list.addAll(Arrays.asList("foo", "bar"));

做吗?它是否递增 changeCount两次,还是根本没有?这取决于是否ArrayList.addAll()使用 add() ,这是您不必担心的实现细节。您还必须使您的方法与 ArrayList 保持同步方法。比如目前addAll(Collection<?> collection) add()之上实现的,但如果他们决定在未来的版本中首先检查是否 collection instanceof ArrayList , 如果是这样使用 System.arraycopy要直接复制数据,您必须更改您的 addAll()仅增加 changeCount 的方法通过 collection.size()如果集合是 ArrayList (否则它会在 add() 中完成)。

此外,如果一个方法被添加到 List (例如,这发生在 forEach()stream() 上)如果您使用该方法名称表示其他含义,这将导致问题。扩展 abstract 时可能会发生这种情况类也是,但至少是abstract类没有状态,因此您不太可能通过覆盖方法造成太大的损害。

我仍然会使用 List接口(interface),并理想地扩展AbstractList .像这样

public final class PayloadList<E> extends AbstractList<E> implements RandomAccess {

private final ArrayList<E> list;
private final Object[] payload;

// details missing
}

这样你就有了一个实现了List的类并利用 ArrayList无需担心实现细节。

(顺便说一句,在我看来,AbstractList 类非常了不起。您只需重写 get()size() 即可获得正常运行的 List 实现和类似 containsAll()toString() 的方法和 stream() 都可以。)

关于java - 扩展List增加字段是否合适,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32481550/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com