Java 扩大番石榴系列

Java 扩大番石榴系列,java,guava,Java,Guava,我想扩展LinkedHashMultimap(Guava16.0.1),主要是添加返回常用预填充贴图的方法 public class MyMap extends LinkedHashMultimap<String, Object> { } 公共类MyMap扩展LinkedHashMultimap{ } 但是,正如我所了解到的,大多数番石榴收集是最终的,而那些不是最终的,不会公开公共构造函数。做出此设计决策的可能原因是什么?实现我的目标的最佳途径是什么?我能想到的最好方法是在我的类

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

public class MyMap extends LinkedHashMultimap<String, Object> {
}
公共类MyMap扩展LinkedHashMultimap{
}
但是,正如我所了解到的,大多数番石榴收集是最终的,而那些不是最终的,不会公开公共构造函数。做出此设计决策的可能原因是什么?实现我的目标的最佳途径是什么?我能想到的最好方法是在我的类中包装Multimap方法,但这远远不够理想

编辑:

一些用户指出了不允许继承的正当理由。为了把问题扩大一点,我想指出两件事

  • 如果在公共API中不推荐继承,为什么Java自己的集合类不是final

  • 假设我广泛使用以下类:

  • LinkedHashMultimap机会是:

  • 在Java 8中向接口添加默认方法(由于集合类型是由Guava库定义的,因此不能添加默认方法)
  • 扩展实现(由于实现大多是最终的,所以您也不能扩展)
  • 为外部助手类提供所需的方法
  • 这些课程的设计不是为了扩展。因为继承本质上破坏了封装,所以当类无法扩展时,它会使API更干净。(此处的相关线程:)

    您通常可以通过使用合成来解决这个问题

    要回答您的后续问题,请执行以下操作:

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

    可能Guava团队认为,像您现在介绍的这样的用例非常罕见,不值得为继承添加支持(YAGNI)


    Josh Bloch——他参与了Java API和Guava的设计——是关于这个主题的一个优秀的演示。

    正如其他人所指出的,您应该更喜欢委托而不是继承

    要实现所需的类,您需要做的是使用
    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
    }
    
    公共最终类MyMap扩展了ForwardingSetMultimap{
    私有最终SetMultimap委托=
    LinkedHashMultimap.create();
    @重写公共SetMultimap委托(){
    返回代表;
    }
    //在这里添加您的方法
    }
    
    旁白:您会问“如果公共API中不推荐继承,为什么Java自己的集合类不是最终类?”


    我认为答案基本上是,不使用Java自己的集合类
    final
    (注意:其中一些类,尤其是较新的类,实际上是
    final
    )。正如@Mick Mememonic所指出的,Josh Bloch(设计原始集合API)参与了Guava集合API的设计:Guava API中的设计决策反映了从原始集合API中吸取的经验教训。

    装饰图案是你的方式吗?如果我理解正确,无论如何,您要添加的方法都没有理由成为实例方法。为什么您只需要扩展LinkedHashMultimap来提供返回预填充映射的实用方法?组合通常比继承更可取,但在这里,似乎您甚至不需要组合:只需要一个实用程序类。你能提供一个你想添加的方法的例子吗?@JBNizet:我意识到我可以通过实用类来实现这一点,这样看起来更干净。顺便说一句,我不明白为什么组合比继承更受欢迎。两者都有合法的用例,而这个用例不是合法的用例,既不是用于继承,也不是用于组合。关于“偏好组合而非继承”,请阅读@JBNizet:在这种情况下,继承不会有危险,因为我只会使用极不可能改变的超类方法,但是,我现在理解了阻止继承的原因。这很好,但我仍然倾向于不同意让课程成为最终课程是一件好事。应该让库的用户来决定他们的用例是否有理由继承。更多的选择几乎总是一件好事。番石榴团队不必努力支持遗传,事实上他们已经努力禁用了它。“更多的选择几乎总是一件好事。”绝对不是。特别是当这些选项使得射中自己的脚变得容易时。扩展集合类时很容易出错。“优先组合而非继承”和“为继承而设计或防止继承”是这里的两个关键设计原则。Guava将正常的实现(如
    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
    }