web-dev-qa-db-ja.com

Kotlin-非データクラスのtoString()を生成する

状況:

lateinitフィールドを持つクラスがあるため、コンストラクターには存在しません。

_class ConfirmRequest() {
    lateinit var playerId: String
}
_

ボイラープリントを回避するために、すべてのフィールドでtoString()メソッドを使用し、手動で書き込みたくないのですが。 In Javaこの問題にはLombok_@ToString_アノテーションを使用します。

質問:

Kotlinで実装する方法はありますか?

23
awfun

推奨される方法は、toStringを手動で記述(またはIDEで生成)し、そのようなクラスが多くなりすぎないようにすることです。

data classの目的は、85%の最も一般的なケースに対応することであり、15%を他のソリューションに残します。

10
voddan

あなたのように、JavaでtoString()equals()にlombokを使用することに慣れていたので、Kotlinの非データクラスがすべての標準ボイラープレートを必要とすることに少しがっかりしました。

そこで、ボイラープレートなしでtoString()equals()を実装できるオープンソースライブラリ Kassava を作成しました。プロパティのリストを指定するだけで完了です。 !

例えば:

// 1. Import extension functions
import au.com.console.kassava.kotlinEquals
import au.com.console.kassava.kotlinToString

import Java.util.Objects

class Employee(val name: String, val age: Int? = null) {

    // 2. Optionally define your properties for equals()/toString() in a  companion
    //    object (Kotlin will generate less KProperty classes, and you won't have
    //    array creation for every method call)
    companion object {
        private val properties = arrayOf(Employee::name, Employee::age)
    }

    // 3. Implement equals() by supplying the list of properties to be included
    override fun equals(other: Any?) = kotlinEquals(
        other = other, 
        properties = properties
    )

    // 4. Implement toString() by supplying the list of properties to be included
    override fun toString() = kotlinToString(properties = properties)

    // 5. Implement hashCode() because you're awesome and know what you're doing ;)
    override fun hashCode() = Objects.hash(name, age)
}
8
James Bassett

Apache Commons LangのToStringBuilderはリフレクションを使用すると便利ですが、必要ない場合はhashCode()およびその他のメソッドを呼び出します(3番目のhashCode()と呼ばれるメソッドはパーティーlibはNPEを生成します)。

だから私はただ行く:

// class myClass
    override fun toString() = MiscUtils.reflectionToString(this)

// class MiscUTils
fun reflectionToString(obj: Any): String {
    val s = LinkedList<String>()
    var clazz: Class<in Any>? = obj.javaClass
    while (clazz != null) {
        for (prop in clazz.declaredFields.filterNot { Modifier.isStatic(it.modifiers) }) {
            prop.isAccessible = true
            s += "${prop.name}=" + prop.get(obj)?.toString()?.trim()
        }
        clazz = clazz.superclass
    }
    return "${obj.javaClass.simpleName}=[${s.joinToString(", ")}]"
}
8
junique

使用するデータを含むデータクラスを定義し、それに委任することでメソッドを実装できます。

https://stackoverflow.com/a/46247234/97777

1
Duncan McGregor

Kotlinリフレクションの使用はどうですか?質問を誤解したり、「Kotlinの非効率的な」例を書いたりした場合、私は数日間Kotlinに夢中です。

override fun toString() : String{
    var ret : String = ""
    for (memberProperty in this.javaClass.kotlin.memberProperties){
        ret += ("Property:${memberProperty.name} value:${memberProperty.get(this).toString()}\n");
    }
    return ret
}

これは、たとえばtoString2Interfaceとしてfun toString2として新しく作成されたインターフェイスに実装することもできます。次に、ToString2Interfaceを実装するすべてのクラスには、toString2()があります。

0
vukis