2024 Clojure 状态调查!中分享您的想法。

欢迎!请查看关于页面了解该机制的更多信息。

0
Java 互操作
编辑于

我想将这段 Java 代码转换为 Clojure

S3Client.builder()
      .serviceConfiguration(S3Configuration.builder()
            .pathStyleAccessEnabled(true)
            .build())
      .build();

问题:`serviceConfiguration` 方法需要一个 java.util.function.Consumer

default B serviceConfiguration(Consumer<S3Configuration.Builder> serviceConfiguration)

serviceConfiguration 方法在此处定义 AWS SDK serviceConfiguration

我尝试使用 reify,但效果不佳。

也许有人可以指明正确的方向,或者已经使用过这个 API 的特定部分。

有人可以告诉我,这样的 API 设计对 Java 开发者有何优势,这个结构的目的是什么?

1 答案

0

被选中为最佳答案
 
最佳答案

鉴于 Java 代码,第三行的 .build() 方法也必须返回一个 Consumer 的实例。因此,无需 reify,您应能够使用以下内容:

(let [consumer (-> (S3Configuration/builder) (.pathStyleAccessEnabled true) (.build))]
  (-> (S3Client/builder) (.seviceConfiguration consumer) (.build)))

这种模式,你创建一个构建者,在其上调用一堆配置方法,然后调用.build方法获得你真正需要的最终对象,这被称为... “构建者”。 :) 在面向对象的世界里,当你想要确保封装性且没有部分构建的对象时,它非常有帮助。它还可以帮助你在需要使用相同接口的多个不同构建者,行为各异的情况下。或者在你必须在不同上下文中分离对象创建的情况下。

感谢你的回答。这也曾是我的第一个方案。

但运行上述代码示例会导致以下异常

```
; (err) 执行错误 (ClassCastException) 在 java.lang.Class/cast (Class.java:3889)。
; (err) 无法将 software.amazon.awssdk.services.s3.S3Configuration 强制转换为 java.util.function.Consumer
```

这就是为什么我尝试使用 reify 的原因

为了澄清:我意思是为什么他们甚至在方法中需要一个 Consumer,这样签名的意义何在
`(Consumer<S3Configuration.Builder> serviceConfiguration)`

感谢你花时间。
明白了。在原文中放入错误通常很有帮助。 ;) `serviceConfiguration` 方法有两个签名 - 一个接受 `Consumer` 的实例,另一个接受 `S3Configuration` 的实例。你可以通过使用 `(.serviceConfiguration ^S3Configuration consumer)` 来诱导 Clojure 编译器使用第二个签名。

关于你的“有什么意义”的问题 - 由于这个问题是关于 AWS JDK 而不是关于 Java 的一般性,所以我不知道。
添加类型提示是可行的。谢谢!

出于好奇,有没有简单的方法可以将其转换为 Consumer?
这些是完全不同的接口,所以没有直接的转换方法。但你可以使用 `reify` 创建一个实现了 `Consumer` 的对象,并可能在那里使用配置。
...