[英]Idiomatic migration from Java to Kotlin of class that accesses inner class private members
我有一个 Java class ( Outer
),它使用内部构建器 class ( Outer.Builder
),访问私有变量作为构造的一部分,如下所示:
import java.io.PrintStream;
public class Outer {
private int mValue;
private Outer(Builder builder) {
mValue = builder.mValue;
}
public void printValue(PrintStream stream) {
stream.println(mValue);
}
public static class Builder {
private int mValue;
public Builder setValue(int value) {
mValue = value;
return this;
}
public Outer build() {
return new Outer(this);
}
}
}
使用如下:
class Main {
public static void main(String[] args) {
var builder = new Outer.Builder();
var outer = builder.setValue(42).build();
outer.printValue(System.out);
}
}
我试图利用 Android Studio 将 Java 代码迁移到 Kotlin 的能力,这给了我以下结果:
import java.io.PrintStream
class Outer private constructor(builder: Builder) {
private val mValue: Int
fun printValue(stream: PrintStream) {
stream.println(mValue)
}
class Builder {
private var mValue = 0
fun setValue(value: Int): Builder {
mValue = value
return this
}
fun build(): Outer {
return Outer(this)
}
}
init {
mValue = builder.mValue
}
}
但是,编译失败,出现:
Outer.kt:24:22: error: cannot access 'mValue': it is private in 'Builder'
mValue = builder.mValue
^
因为(如Kotlin 文档所述):
在 Kotlin 中,外部 class 看不到其内部类的私有成员。
这段代码在init
块中运行,与:
mValue = builder.mValue
我知道我可以重构它以不尝试此访问(更改Outer
构造函数以使其获取所有成员,将访问器添加到Outer.Builder
以获取必要的字段等),但我想知道是否存在是一种惯用的 Kotlin 方式来实现这种构建器模式(如果可能,对初始 Java class 进行最小修改)。
Kotlin命名为 arguments ,因此整个 Builder 模式嵌入到语言中:
class Outer(private val mValue: Int = 0) {
fun printValue(stream: PrintStream) = stream.println(mValue)
}
//Usage:
fun main() {
val outer = Outer(mValue = 42)
outer.printValue(System.out)
}
但是,这种方法仅适用于 Kotlin 的使用。 对于 Java 的用法,构造函数应变为私有,并且应声明传统的嵌套生成器:
class Outer private constructor(val mValue: Int) {
class Builder {
@set:JvmSynthetic // Hide 'void' setter from Java
var mValue: Int = 0
fun setValue(value: Int) = apply { this.mValue = value }
fun build() = Outer(mValue)
}
fun printValue(stream: PrintStream) = stream.println(mValue)
}
为了方便地从 Kotlin 创建Outer
,我们需要声明一个辅助顶级 function,其名称与我们可以用来复制构造函数的类型相同:
@JvmSynthetic // Hide from Java callers who should use Builder.
fun Outer(initializer: Outer.Builder.() -> Unit): Outer {
return Outer.Builder().apply(initializer).build()
}
来自 Java 的用法:
public class BuilderUsage {
public static void main(String[] args) {
Outer outer = new Outer.Builder().setValue(42).build();
outer.printValue(System.out);
}
}
Kotlin 的用法:
fun main() {
val outer = Outer { mValue = 42 }
outer.printValue(System.out)
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.