扩展番石榴收藏品

Nik*_*dun 4 java guava

我想扩展LinkedHashMultimap(Guava 16.0.1),主要是添加返回常用预填充地图的方法.

public class MyMap extends LinkedHashMultimap<String, Object> {
}
Run Code Online (Sandbox Code Playgroud)

但是,正如我所知,大多数番石榴收藏品是最终的,而那些不是,不会暴露公共建设者.这个设计决定的可能原因是什么?什么是实现我的目标的最佳方法?我能想到的最好的方法是在我的课程中包装Multimap方法,但这远非理想.

编辑:

一些用户指出了不允许继承的正当理由.为了稍微扩展问题,我想指出几点.

  1. 如果不建议在公共API中继承,那么为什么Java自己的集合类不是最终的?

  2. 假设我广泛使用以下类:

LinkedHashMultimap <类<?扩展BaseEntity>,BiConsumer <?扩展BaseEntity,?extends Object >>

现在,这是一个满口.如果我可以:

public class ConsumerMap extends LinkedHashMultimap<Class<? extends BaseEntity>, BiConsumer<? extends BaseEntity, ? extends Object>> {
}
Run Code Online (Sandbox Code Playgroud)

然后我可以在我的代码中使用ConsumerMap而不是那个怪物.我相信只有可读性才足以证明继承的合理性.

Col*_*inD 6

正如其他人所指出的,你应该更喜欢委托继承.

您想要实现所需类的目的是ForwardingSetMultimap使用a LinkedHashMultimap作为委托进行扩展.这是一个看起来如何的例子:

public final class MyMap extends ForwardingSetMultimap<String, Object> {
  private final SetMultimap<String, Object> delegate =
      LinkedHashMultimap.create();

  @Override public SetMultimap<String, Object> delegate() {
    return delegate;
  }

  // add your methods here
}
Run Code Online (Sandbox Code Playgroud)

旁白:你问"如果在公共API中不推荐继承,那么Java自己的集合类怎么不是最终的呢?"

我认为答案基本上是错误的,而不是制作Java自己的集合类final(注意:其中一些,特别是新的,实际上是final).正如@Mick Mnemonic所说,Josh Bloch(他设计了原始集合API)参与了Guava集合API的设计:Guava API的设计决策反映了从原始集合API中汲取的经验教训.


Mic*_*nic 5

这些类设计为不可扩展。因为继承本质上破坏了封装,所以当类不能扩展时,它使 API 更干净。(此处的相关主题:在 Java 中禁止继承的充分理由?

您通常可以通过使用组合来解决此问题。

要回答您的后续问题:

关于 Java Collections API,我认为有两种选择:要么类像ArrayListHashMap旨在扩展,要么这只是 API 设计缺陷。我怀疑是后者;但是在 API 发布后就不可能恢复这个设计选择。也许只有抽象类AbstractList应该被声明为非最终类?

可能 Guava 团队认为像您展示的用例这样的用例非常罕见,以至于不值得努力添加对继承的支持 (YAGNI)。

参与设计 Java API 和 Guava 的 Josh Bloch 的这次演讲是关于该主题的出色演讲。

  • “更多的选择几乎总是一件好事。” 绝对不。特别是当这些选项可以轻松地用脚射击时。扩展集合类时很容易做错事。“优先组合而不是继承”和“为继承而设计,否则阻止它”是这里的两个关键设计原则。Guava 将像 LinkedHashMultimap 这样的普通实现与专为继承而设计的实现(“Forwarding-”类)分开。 (2认同)