【问题标题】:Is is acceptable to declare a private class as an alias?将私有类声明为别名是否可以接受?
【发布时间】:2023-03-08 14:56:01
【问题描述】:

在my answer from yesterday 中,我将以下代码称为“黑客”:

final class MyMap extends HashMap<SomeSuperLongIdentifier, OtherSuperLongIdentifier> {}
// declared MyMap as an alias for readability purposes only

MyMap a = new MyMap();
a.put("key", "val");

再想一想,这似乎不是一个坏主意,但我可能会遗漏一些东西。有没有我错过的坑洼?这是在 Java 中声明别名的可接受(可能是创造性的)方式吗?

【问题讨论】:

  • 根据建议添加了 final 修饰符...

标签: java


【解决方案1】:

缺点是您将无法直接使用任何返回正确类型的Map 的方法,因为它们永远不会返回MyMap。即使他们可以返回Map&lt;SomeSuperLongIdentifier, OtherSuperLongIdentifier&gt;。

例如,您将无法使用Maps(由Google Collections 提供)中的filter() 方法。他们会接受 MyMap 实例作为输入,但他们只会返回 Map&lt;SomeSuperLongIdentifier, OtherSuperLongIdentifier&gt;。

可以通过编写MyMap 委托给另一个Map 实现来稍微减少这个问题。然后你可以将这种方法的返回值传递给构造函数,并且仍然有一个MyMap(甚至没有复制)。默认构造函数可以将委托设置为新的HashMap 实例,因此默认用法将保持不变。

【讨论】:

    【解决方案2】:

    我反对MyMap这个名字:既然你创建了一个别名,那就给它一个有用的名字来证明它的目的。除此之外,我喜欢它。

    【讨论】:

    • MyMap 只是一个示例名称,当然在实际代码中这应该是一个有意义的名称。
    【解决方案3】:

    我认为这无疑是一种声明类型同义词的便捷方式。某些语言对此有直接支持(例如,在 Delphi (pascal) 中,您可以这样做:

    type MyMap =  HashMap<SomeSuperLongIdentifier, OtherSuperLongIdentifier>;
    

    由于 Java 没有,我认为您可以为此使用继承。您需要记录,此声明只是一个同义词,没有人应该向此类添加方法。另请注意,这会消耗少量内存用于 VMT 存储。

    【讨论】:

    • 为了确保没有人可以添加方法,只需声明final
    • @Aaron Digulla。这仅适用于子类。稍后有人可能会出现并向MyMap 添加方法,而final 不会阻止它。
    • 这样的类型同义词可能很有用,但在 Java 中是不可能的。子类不是同义词。
    • @Joachim Sauer:但它的功能几乎是一样的,不是吗?
    • 不幸的是不是(取决于您对“几乎”的定义)。子类是子类型。这意味着它可以在任何需要原始类型的地方使用。但问题是相反的情况并非如此(见我的回答)。
    【解决方案4】:

    我个人不会这样做,并会在评论中标记它,但这是一个见仁见智的问题。

    Google Collections 允许您声明:

    Map<SomeSuperLongIdentifier, OtherSuperLongIdentifier> a = Maps.newHashMap();
    

    也许我会寻找方法来重构代码,从而不必声明如此多的 Map 实例。

    【讨论】:

      【解决方案5】:

      只要使用您的代码的开发人员有 IDE 并且能够快速跳转到类定义并读取用于其目的的 cmets(它们已经到位,不是吗?),我看不出它有什么问题。

      【讨论】:

      • 此外,别名问题并没有那么糟糕,因为 OP 询问了“私有”类,因此“别名”没有泄漏。
      【解决方案6】:

      我不会称它为“别名”。它不是。它不能与它应该是别名的类型互换使用。因此,如果这是意图,它会失败。

      【讨论】:

        【解决方案7】:

        我认为与手头的问题相比,继承是一把非常大的枪。至少我会制作这个“别名类”final,并附上一个大注释来描述它存在的原因。

        【讨论】:

        • 您还必须决定您选择公开的构造函数。
        【解决方案8】:

        嗯,这里有两个矛盾的方面。

        1. 从建模的角度来看,您的声明正确,因为它强调了您的类提供的封装。
        2. 从编码的角度来看,您的声明可能会被视为错误,因为您添加的类只是作为建模支持,绝对没有添加任何功能。

        但是,我发现您的方法非常正确(尽管我以前从未想过),因为它提供了一个非常受欢迎的(至少对我而言)可编译模型:您模型中的类完美地反映在您的代码中,使您的规范可执行,这非常酷。

        所有这一切让我想说这绝对是一个好主意,只要你用文档支持它。

        【讨论】:

          【解决方案9】:

          我不会称其为 hack。就个人而言,我创建了一个别名,目的是声明无法更改的泛型类型参数并创建一些清晰度。

          【讨论】:

            【解决方案10】:

            如果发送到另一个没有您的 MyMap 类的 jvm,您也不能在序列化中使用此映射。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2010-10-13
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2017-04-11
              相关资源
              最近更新 更多