嗨,我是Kotlin世界的新手。我喜欢我目前所看到的,并开始考虑将我们在应用程序中使用的一些库从Java转换为Kotlin。

这些库充满了带有setter、getter和Builder类的pojo。现在我已经在谷歌上找到了在Kotlin中实现Builders的最佳方法,但没有成功。

第二次更新:问题是如何写一个建设者设计模式的一个简单的pojo与一些参数在Kotlin?下面的代码是我尝试编写java代码,然后使用eclipse-kotlin-plugin转换为Kotlin。

class Car private constructor(builder:Car.Builder) {
    var model:String? = null
    var year:Int = 0
    init {
        this.model = builder.model
        this.year = builder.year
    }
    companion object Builder {
        var model:String? = null
        private set

        var year:Int = 0
        private set

        fun model(model:String):Builder {
            this.model = model
            return this
        }
        fun year(year:Int):Builder {
            this.year = year
            return this
        }
        fun build():Car {
            val car = Car(this)
            return car
        }
    }
}

当前回答

对于简单类,不需要单独的构建器。您可以像Kirill Rakhman描述的那样使用可选的构造函数参数。

如果你有更复杂的类,那么Kotlin提供了一种方法来创建Groovy风格的Builders/DSL:

类型安全的建筑商

这里有一个例子:

Github示例-构建器/汇编器

其他回答

我在一个Kotlin项目中工作,该项目公开了一个由Java客户机使用的API (Java客户机不能利用Kotlin语言结构)。我们必须添加构建器以使它们在Java中可用,因此我创建了@Builder注释:https://github.com/ThinkingLogic/kotlin-builder-annotation 它基本上是Kotlin的Lombok @Builder注释的替代品。

我看到过许多将额外乐趣作为构建者的例子。我个人喜欢这种方法。节省编写构建程序的精力。

package android.zeroarst.lab.koltinlab

import kotlin.properties.Delegates

class Lab {
    companion object {
        @JvmStatic fun main(args: Array<String>) {

            val roy = Person {
                name = "Roy"
                age = 33
                height = 173
                single = true
                car {
                    brand = "Tesla"
                    model = "Model X"
                    year = 2017
                }
                car {
                    brand = "Tesla"
                    model = "Model S"
                    year = 2018
                }
            }

            println(roy)
        }

        class Person() {
            constructor(init: Person.() -> Unit) : this() {
                this.init()
            }

            var name: String by Delegates.notNull()
            var age: Int by Delegates.notNull()
            var height: Int by Delegates.notNull()
            var single: Boolean by Delegates.notNull()
            val cars: MutableList<Car> by lazy { arrayListOf<Car>() }

            override fun toString(): String {
                return "name=$name, age=$age, " +
                        "height=$height, " +
                        "single=${when (single) {
                            true -> "looking for a girl friend T___T"
                            false -> "Happy!!"
                        }}\nCars: $cars"
            }
        }

        class Car() {

            var brand: String by Delegates.notNull()
            var model: String by Delegates.notNull()
            var year: Int by Delegates.notNull()

            override fun toString(): String {
                return "(brand=$brand, model=$model, year=$year)"
            }
        }

        fun Person.car(init: Car.() -> Unit): Unit {
            cars.add(Car().apply(init))
        }

    }
}

我还没有找到一种方法,可以强制在DSL中初始化一些字段,比如显示错误而不是抛出异常。如果有人知道就告诉我。

在kotlin中可以使用可选参数 例子:

fun myFunc(p1: String, p2: Int = -1, p3: Long = -1, p4: String = "default") {
    System.out.printf("parameter %s %d %d %s\n", p1, p2, p3, p4)
}

然后

myFunc("a")
myFunc("a", 1)
myFunc("a", 1, 2)
myFunc("a", 1, 2, "b")

我迟到了。如果我必须在项目中使用Builder模式,我也遇到了同样的困境。后来,经过研究,我意识到这是完全不必要的,因为Kotlin已经提供了命名参数和默认参数。

如果你真的需要实施,Kirill Rakhman的答案是关于如何以最有效的方式实施的可靠答案。您可能会发现另一件有用的事情是https://www.baeldung.com/kotlin-builder-pattern,您可以将其与Java和Kotlin的实现进行比较和对比

我在Kotlin中实现了一个基本的Builder模式,代码如下:

data class DialogMessage(
        var title: String = "",
        var message: String = ""
) {


    class Builder( context: Context){


        private var context: Context = context
        private var title: String = ""
        private var message: String = ""

        fun title( title : String) = apply { this.title = title }

        fun message( message : String ) = apply { this.message = message  }    

        fun build() = KeyoDialogMessage(
                title,
                message
        )

    }

    private lateinit var  dialog : Dialog

    fun show(){
        this.dialog= Dialog(context)
        .
        .
        .
        dialog.show()

    }

    fun hide(){
        if( this.dialog != null){
            this.dialog.dismiss()
        }
    }
}

最后

Java:

new DialogMessage.Builder( context )
       .title("Title")
       .message("Message")
       .build()
       .show();

科特林:

DialogMessage.Builder( context )
       .title("Title")
       .message("")
       .build()
       .show()