【问题标题】:Why is requires transitive limited to the modules that directly require the module containing it?为什么需要传递仅限于直接需要包含它的模块的模块?
【发布时间】:2018-04-27 22:26:25
【问题描述】:

假设有模块x 可以导出一些东西。 然后是模块a

module a {
 exports some.package.from.a
 requires transitive x;
}

那么有100个模块b需要a

module b1 {
  exports some.package.from.b1
  requires a;
}
...
module b100 {
  exports some.package.from.b100
  requires a;
}

那么有 100 个模块 c 需要各自的 bs

module c1 {
  requires b1;
}

...
module c100 {
  requires b100;
}

假设c1 ... c100 不需要知道来自a 的包。这些仅由 b1 ... b100 在内部使用,因此不需要传递。

但是b1 ... b100 导出的API 使用x 导出的包中的类。

模块 c1 ... c100 看不到这些。尝试编译它们,结果是

Compilation failure:
(package x.y.z is declared in module x, but module c1 does not read it)

为什么requires transitive 仅限于直接需要包含它的模块的模块?如果不编辑 100 个module-info 文件,如何解决上述问题?


更新: 至少有 3 种方法可以“解决”这个问题:

  • requires transitive a 添加到b1 ... b100
  • requires transitive x 添加到b1 ... b100
  • requires x 添加到c1 ... c100

虽然在这种特殊情况下所有方法都可以工作,但尚不清楚应该使用哪一种以及每种方法的副作用是什么。此外,这只是 3 级深层次结构 - 层次越多,它就越复杂。

如果requires transitive 对所有家属都是可传递的(正如传递这个词所暗示的),这将自动解决。如果没有transitive,则只有一种方法可以解决该问题。 transitive 仅限于直接家属,因此需要考虑“选项”,但似乎没有提供足够的信息供人们做出正确选择。

【问题讨论】:

  • 听起来你在寻找increase the module readability
  • 也许吧!我只是想了解这个限制背后的设计决策来自哪里。我找不到任何解释。我知道根据 Java 语言规范的第 7.7.1 节,“正确”的方法是将 requires transitive a 添加到所有 b 模块中。然而,这看起来违反直觉。此外,出于任何其他原因,它根本没有必要,而是使x 在不止一个级别上具有传递性。

标签: java java-9 java-platform-module-system java-module module-info


【解决方案1】:

如果一个模块(你的 b 的)使用另一个模块的(你的 x)类型独立于穿插的需要传递(b' s 在 a 上),它们应该直接要求它们并且依赖于隐含的可读性。

在你的情况下,b 绝对应该是@​​987654321@。

【讨论】:

  • 你怎么知道它应该是这样的?也许你是对的,但我不清楚你是如何得出这个结论的?这基本上是我的问题 - 为什么必须以特定方式完成。考虑到这种方法创造的所有可能性,人们如何知道使用哪一种(参见更新后的问题)?
  • @MilenDyankov 我认为问题中的这一行很重要:“但是 b1 ... b100 导出的 API 使用 x 导出的包中的类。” bK API 的任何消费者都需要说 requires bK。从您的声明来看,该 API 还将使用来自 x 的类型,因此 bK 的模块声明也应该是 requires transitive x
  • @MilenDyankov JLS 7.7.1 示例与您的示例不同;没必要盲目跟风。模块 bK 肯定使用来自 x 的类型,所以它至少必须说 requires x。 bK 的 API 由其客户端 cK 使用,也使用来自 x 的类型。因此模块 cK 需要requires bK。但是,如果每个 cK also 都必须声明 requires x,它的效果会很差。由于要求 bK 意味着也需要 x,因此 bK 可以通过声明 requires transitive x 来说明这一点,以便 x 被“传递”给 bK 的客户。
  • @MilenDyankov 假设模块 b 声明 requires x 而不是 requires transitive x,如前所述,b 的 API 使用来自 x 的类型。模块 c 需要使用 b,所以它声明了requires b。这失败了,因为 b 的 API 不能被 c 使用,因为 x 的类型不能从 c 中读取。这是 b 声明中的错误; b 的客户端不能在没有 x 的情况下使用它的 API,因此 b 应该声明 requires transitive x。可以通过让 c 声明 requires x解决此错误,但这并不能解决根本错误。
  • @MilenDyankov 所以这就是为什么 b 声明 requires transitive x(方法 2)优于 c 声明 requires x(方法 3)。现在考虑 b 声明 requires transitive a(方法 1)。在你所说的问题中 假设 c 不需要知道来自 a 的包。这些仅由 b 在内部使用,因此不需要传递。 让 b 声明 requires transitive a 意味着 a 对 b 的客户(例如 c)是可读的,这与您的陈述相矛盾。因此,方法一是不正确的。
猜你喜欢
  • 1970-01-01
  • 2020-10-02
  • 2016-08-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-26
相关资源
最近更新 更多