【问题标题】:Why should the Java compiler not support inheritance of imports?为什么 Java 编译器不支持导入继承?
【发布时间】:2012-12-28 19:45:08
【问题描述】:

在 Java 中,导入与(外部)类相关,因为每个(外部)类都应该编码在单独的文件中。因此,可以声称类定义之前的import ...; 指令与类相关联(有点像注释)。

现在,如果可以继承父类的导入,那将大大减少源文件的混乱。为什么这不可能?即为什么 Java 编译器不应该考虑基类的导入?

注意事项:

  • 可能有不止一个答案。
  • 我知道如果您让 eclipse 组织您的导入,这不是什么大问题,无需提及。这是关于“为什么”,而不是“如何” (a-la-this)。

【问题讨论】:

  • 您可以在一个文件中声明多个类。导入与文件相关,而不是类。
  • 如果父类导入java.lang.annotation.Annotation 并且在子类中您想使用java.text.Annotation。如果导入是继承的,这会很复杂。
  • 我让我的 IDE 管理所有导入并将它们折叠起来,所以我什至看不到它们。我发现我不必经常考虑它们。
  • 导入是语法糖,仅此而已。如果你真的想的话,你可以编写任何 Java 程序而无需使用 import 语句。

标签: java inheritance import compilation


【解决方案1】:

首先,重要的是要注意,并非每个类都必须编码在单独的文件中——而是每个公共的顶级类都必须是。不,导入并没有真正与任何类相关联——它们只是用于在文件中包含某些外部类/包的语句,以便可以使用它们。事实上,你永远不需要实际导入任何东西,你总是可以使用全名,即:

java.util.List<String> list = new java.util.ArrayList<String>();

导入是为了方便(并且仅用于编译器 - 在编译类后它们会丢失),以使您不必写出所有内容,而只让您编写 List&lt;String&gt; list = new ArrayList&lt;String&gt;(在您制作相关的从java.util 导入)。因此,没有理由让子类“继承”导入。

【讨论】:

  • +1 每个公共的顶级类必须在它自己的文件中。公共嵌套类可以共享一个文件。
  • +1 并且我认为明确声明导入仅用于编译器是很重要的(或者为了便于阅读以避免完全限定名称 - 无论您喜欢哪个原因)。类编译后它们会丢失。
  • 谢谢,做了这些澄清。
  • 你的结论不是你的前提的结果。导入是一种方便的工具这一事实并不是它们不被“继承”的原因,至少在编译的上下文中是这样。即使编译完成后所有这些信息都被丢弃,编译器也可以知道父类的导入。
  • @einpoklum 这暗示导入与任何特定类无关,这就是为什么以任何方式继承它们都没有意义——因为它们与任何超类无关。跨度>
【解决方案2】:

导入只是语法糖,仅此而已。如果您真的愿意,您可以编写任何 Java 程序而无需使用 import 语句。例如,下面的类都是自己编译的:

class Foo {
  java.util.List<String> list = new java.util.ArrayList<String>();
}

此外,继承导入使得从类中删除导入变得非常非常困难。例如,如果Bar.java 继承自Foo.java,则您可能无法从Foo 中删除导入而不将其添加到Bar。强制导入显式使更改单个文件变得更加容易,而不必担心对其他文件的影响,这几乎是 Java 和面向对象编程的基本原则。

(最后一点与 a significant factor in the design of Go 的问题有关,它专门试图避免 C 和 C++ 在这方面的问题。)

【讨论】:

  • 所以,您是说从 Foo 删除导入需要重新编译 Bar 可能会失败。但是,为什么会有这样的问题?让我们失败,让 Bar 的作者自己进行导入。无论如何,这是她/他今天需要做的,对吧?
  • 在您提出的方案中,Foo 导入 Baz,Bar 导入 Foo 但也需要 Baz。如果 Foo 想删除 Baz 导入,那么 Bar 突然不再从 Foo 获取 Baz,并且必须重写,而不仅仅是重新编译。这就是问题所在。
  • 这是怎么回事?假设 Bar 从 Foo 继承了一个方法,并且从 Foo 中删除了该方法。那也需要重写。 Foo 对 Baz 的继承也是如此。一旦你将导入与一个类相关联,这就变得合理了。恕我直言。
  • 改变Foo的实现和改变Foo的API是有区别的。 Java 可以很容易地更改 Foo 的实现,而无需修改 Foo 的用户,而您的提议会使这变得困难。没有一种语言可以在不改变 Foo 用户的情况下轻松改变 Foo 的 API。
【解决方案3】:

让每个文件明确指定其导入可以提高可读性。想象一下,打开一个文件并不能一眼看到依赖项,因为导入是从另一个文件继承的。

【讨论】:

  • 我不需要想象,我在现实生活中拥有它:在大多数其他语言中,您“导入”自己“导入”其他东西的东西,例如包含 C 和 C++ 中的文件。
  • ... 并且拥有 70 个导入并不能真正提高可读性(当然,除非您是编译器)。
猜你喜欢
  • 2011-04-15
  • 2016-04-18
  • 2014-03-04
  • 2010-11-16
  • 2011-05-23
  • 2013-07-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多