Kotlin中的生成器模式
我是科特林世界的新手。我有一个用Java编写的现有构建器,并希望在将项目迁移到Android中的Kotlin时将其转换为Kotlin。然而,Android Studio内置工具似乎有一些bug,然后转换的代码是不可编译的。它显示myKotlin中的生成器模式,kotlin,Kotlin,我是科特林世界的新手。我有一个用Java编写的现有构建器,并希望在将项目迁移到Android中的Kotlin时将其转换为Kotlin。然而,Android Studio内置工具似乎有一些bug,然后转换的代码是不可编译的。它显示myUserBuilder类中的变量无法访问 下面是来自 自动转换的kotlin代码: class Person private constructor(builder: UserBuilder) { val firstName: String // requir
UserBuilder
类中的变量无法访问
下面是来自
自动转换的kotlin代码:
class Person private constructor(builder: UserBuilder) {
val firstName: String // required
val lastName: String // required
val age: Int // optional
val phone: String // optional
val address: String // optional
init {
//cannot access the variables, they are private in UserBuilder
this.firstName = builder.firstName
this.lastName = builder.lastName
this.age = builder.age
this.phone = builder.phone
this.address = builder.address
}
class UserBuilder(private val firstName: String, private val lastName: String) {
private var age: Int = 0
private var phone: String? = null
private var address: String? = null
fun age(age: Int): UserBuilder {
this.age = age
return this
}
fun phone(phone: String): UserBuilder {
this.phone = phone
return this
}
fun address(address: String): UserBuilder {
this.address = address
return this
}
fun build(): Person {
return Person(this)
}
}
}
更新
class Person private constructor(builder: UserBuilder) {
val firstName: String // required
val lastName: String // required
val age: Int // optional
val phone: String? // optional
val address: String? // optional
init {
this.firstName = builder.firstName
this.lastName = builder.lastName
this.age = builder.age
this.phone = builder.phone
this.address = builder.address
}
class UserBuilder(internal val firstName: String, internal val lastName: String) {
internal var age: Int = 0
internal var phone: String? = null
internal var address: String? = null
fun age(age: Int): UserBuilder {
this.age = age
return this
}
fun phone(phone: String): UserBuilder {
this.phone = phone
return this
}
fun address(address: String): UserBuilder {
this.address = address
return this
}
fun build(): Person {
return Person(this)
}
}
}
只需像以前一样进行简单的转换 现在您将看到,
UserBuilder
将具有internal
access修饰符,只需删除该修饰符并添加public或任何您需要的内容即可
编辑1 好的,
internal
关键字不在您的Kotlin
代码中,我在检查代码时忽略了这一点
所以现在您需要做的是在Person
类中创建一个对象,并将UserBuilder
类放在其中
检查以下代码:
class Person private constructor(builder: Builder.UserBuilder) {
val firstName: String // required
val lastName: String // required
val age: Int // optional
val phone: String // optional
val address: String // optional
init {
//cannot access the variables, they are private in UserBuilder
this.firstName = builder.firstName
this.lastName = builder.lastName
this.age = builder.age
this.phone = builder.phone
this.address = builder.address
}
object Builder {
class UserBuilder(private val firstName: String, private val lastName: String) {
private var age: Int = 0
private var phone: String? = null
private var address: String? = null
fun age(age: Int): UserBuilder {
this.age = age
return this
}
fun phone(phone: String): UserBuilder {
this.phone = phone
return this
}
fun address(address: String): UserBuilder {
this.address = address
return this
}
fun build(): Person {
return Person(this)
}
}
}
}
这应该像在Java代码中一样工作
希望它能有所帮助。考虑到它是Kotlin,您实际上可以使用数据类将其简化得多
data class User(val firstName: String,
val lastName: String,
val age: Int = 0,
val phone: String? = null,
val address: String? = null)
就这样!前两个参数是必需的,但如果要指定更多参数,只需按名称指定:
val user = User("John", "Doe", phone = "555-1212")
不需要建筑工人
class Person private constructor(builder: UserBuilder) {
val firstName: String // required
val lastName: String // required
val age: Int // optional
val phone: String // optional
val address: String // optional
init {
this.firstName = builder.firstName
this.lastName = builder.lastName
this.age = builder.age
this.phone = builder.phone
this.address = builder.address
}
class UserBuilder(private val _firstName: String, private val _lastName: String) {
private var _age: Int = 0
private var _phone: String? = null
private var _address: String? = null
var firstName: String
get() = this._firstName
var lastName: String
get() = this._lastName
var age: Int = 0
get() = this._age
var phone: String? = null
get() = this._phone
var address: String? = null
get() = this._address
fun age(age: Int): UserBuilder {
this._age = age
return this
}
fun phone(phone: String): UserBuilder {
this._phone = phone
return this
}
fun address(address: String): UserBuilder {
this._address = address
return this
}
fun build(): Person {
return Person(this)
}
}
}
以这种方式使用自定义getter可以解决私有访问修饰符问题。您好,谢谢您的帮助。我知道kotlin有可选的params支持,但我仍然希望有builder,因为我的kotlin库将在Java中使用。这并不能真正取代builder模式。@抗坏血酸取决于您需要builder做什么。如果您需要捕获一个生成器引用并直接使用它,那么这可能不适合您。如果您只是使用构建器从Java端提供默认值和/或简化构造函数,那么这实际上是一种替代。另外,请看一看如何使用@JVMLowloads构造函数生成Java中所需的每个构造函数排列,如果您同意从Java构建器更改为只调用单个构造函数,那么您的解决方案似乎仍然不适合我。它显示了相同的可访问性错误。最后,我将
UserBuilder
中的实例变量更改为internal,以便Person
访问它。我忘了提到该方法将从其他模块调用。我已经检查了上面的代码,它可以从不同的模块正常工作。如果您遗漏了什么,请重新检查。一个与另一个相结合是一个糟糕的建筑设计。如果您能提供更好的想法,我很想看看它在Kotlin的工作原理,因为我是Kotlin世界的新手。很抱歉,我使用手机,我认为KCopock的答案满足您的需求。我说的是:“User
不应该依赖于UserBuilder
”,:)
class Person private constructor(builder: UserBuilder) {
val firstName: String // required
val lastName: String // required
val age: Int // optional
val phone: String // optional
val address: String // optional
init {
this.firstName = builder.firstName
this.lastName = builder.lastName
this.age = builder.age
this.phone = builder.phone
this.address = builder.address
}
class UserBuilder(private val _firstName: String, private val _lastName: String) {
private var _age: Int = 0
private var _phone: String? = null
private var _address: String? = null
var firstName: String
get() = this._firstName
var lastName: String
get() = this._lastName
var age: Int = 0
get() = this._age
var phone: String? = null
get() = this._phone
var address: String? = null
get() = this._address
fun age(age: Int): UserBuilder {
this._age = age
return this
}
fun phone(phone: String): UserBuilder {
this._phone = phone
return this
}
fun address(address: String): UserBuilder {
this._address = address
return this
}
fun build(): Person {
return Person(this)
}
}