को लागू करने नमूदार गुण है कि कर सकते हैं भी serialize में Kotlin

0

सवाल

मैं कोशिश कर रहा हूँ का निर्माण करने के लिए एक वर्ग जहां कुछ मूल्यों नमूदार हैं, लेकिन यह भी Serializable.

जाहिर है, यह काम करता है और क्रमबद्धता काम करता है, लेकिन यह बहुत बॉयलरप्लेट-भारी होने के जोड़ने के लिए एक सेटर के लिए हर एक क्षेत्र और मैन्युअल रूप से कॉल करने के लिए होने change(...) हर सेटर:

interface Observable {

    fun change(message: String) {
        println("changing $message")
    }
}

@Serializable
class BlahVO : Observable {

    var value2: String = ""
        set(value) {
            field = value
            change("value2")
        }

    fun toJson(): String {
        return Json.encodeToString(serializer(), this)
    }
}

println(BlahVO().apply { value2 = "test2" }) सही ढंग से outputs

changing value2
{"value2":"test2"}

मैंने कोशिश की है परिचय के प्रतिनिधियों:

interface Observable {

    fun change(message: String) {
        println("changing $message")
    }

    
    @Suppress("ClassName")
    class default<T>(defaultValue: T) {

        private var value: T = defaultValue

        operator fun getValue(observable: Observable, property: KProperty<*>): T {
            return value
        }

        operator fun setValue(observable: Observable, property: KProperty<*>, value: T) {
            this.value = value
            observable.change(property.name)
        }

    }

}

@Serializable
class BlahVO : Observable {

    var value1: String by Observable.default("value1")

    fun toJson(): String {
        return Json.encodeToString(serializer(), this)
    }
}

println(BlahVO().apply { value1 = "test1" }) सही ढंग से चलाता परिवर्तन का पता लगाने, लेकिन यह नहीं serialize:

changing value1
{}

अगर मैं जाने से नमूदार करने के लिए ReadWriteProperty,

interface Observable {

    fun change(message: String) {
        println("changing $message")
    }

    fun <T> look(defaultValue: T): ReadWriteProperty<Observable, T> {
        return OP(defaultValue, this)
    }

    class OP<T>(defaultValue: T, val observable: Observable) : ObservableProperty<T>(defaultValue) {
        override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
            super.setValue(thisRef, property, value)
            observable.change("blah!")
        }
    }
}

@Serializable
class BlahVO : Observable {

    var value3: String by this.look("value3")

    fun toJson(): String {
        return Json.encodeToString(serializer(), this)
    }
}

परिणाम एक ही है:

changing blah!
{}

इसी प्रकार के प्रतिनिधियों के लिए.vetoable

var value4: String by Delegates.vetoable("value4", {
        property: KProperty<*>, oldstring: String, newString: String ->
    this.change(property.name)
    true
})

outputs:

changing value4
{}

प्रतिनिधियों बस नहीं लगता है के साथ काम Kotlin क्रमबद्धता

क्या अन्य विकल्प वहाँ रहे हैं निरीक्षण करने के लिए एक संपत्ति के परिवर्तन को तोड़ने के बिना अपने क्रमबद्धता होगा कि यह भी काम पर अन्य प्लेटफार्मों (KotlinJS, KotlinJVM, एंड्रॉयड, ...)?

1

सबसे अच्छा जवाब

2

क्रमबद्धता और अक्रमांकन के Kotlin के प्रतिनिधियों के द्वारा समर्थित नहीं है kotlinx.serialization अब के रूप में.
वहाँ है एक खुला मुद्दा #1578 GitHub पर इस सुविधा के बारे में.

अनुसार करने के लिए इस मुद्दे को आप कर सकते हैं बनाने के लिए एक मध्यवर्ती डेटा स्थानांतरण वस्तु हो जाता है, जो धारावाहिक के बजाय मूल वस्तु है । यह भी तुम लिख सकते हैं एक कस्टम serializer का समर्थन करने के लिए क्रमबद्धता के Kotlin प्रतिनिधियों लगता है, जो किया जा करने के लिए और भी अधिक बॉयलरप्लेट, तो लेखन कस्टम getters और setters, के रूप में प्रस्तावित सवाल है ।


डेटा स्थानांतरण वस्तु

मानचित्रण द्वारा अपने मूल वस्तु के लिए एक सरल डेटा स्थानांतरण के बिना वस्तु के प्रतिनिधियों, आप उपयोग कर सकते हैं डिफ़ॉल्ट क्रमबद्धता तंत्र. यह भी अच्छा पक्ष प्रभाव पड़ता है शुद्ध करने के लिए अपने डेटा मॉडल से कक्षाओं ढांचे विशिष्ट एनोटेशन, इस तरह के रूप में @Serializable.

class DataModel {
    var observedProperty: String by Delegates.observable("initial") { property, before, after ->
        println("""Hey, I changed "${property.name}" from "$before" to "$after"!""")
    }

    fun toJson(): String {
        return Json.encodeToString(serializer(), this.toDto())
    }
}

fun DataModel.toDto() = DataTransferObject(observedProperty)

@Serializable
class DataTransferObject(val observedProperty: String)

fun main() {
    val data = DataModel()
    println(data.toJson())
    data.observedProperty = "changed"
    println(data.toJson())
}

इस पैदावार में निम्नलिखित परिणाम:

{"observedProperty":"initial"}
Hey, I changed "observedProperty" from "initial" to "changed"!
{"observedProperty":"changed"}

कस्टम डेटा प्रकार

यदि बदलने के डेटा प्रकार के एक विकल्प है, आप लिख सकते हैं एक लपेटन वर्ग है जो हो जाता है (de)धारावाहिक पारदर्शी. की तर्ज साथ कुछ के बाद काम हो सकता है.

@Serializable
class ClassWithMonitoredString(val monitoredProperty: MonitoredString) {
    fun toJson(): String {
        return Json.encodeToString(serializer(), this)
    }
}

fun main() {
    val monitoredString = obs("obsDefault") { before, after ->
        println("""I changed from "$before" to "$after"!""")
    }
    
    val data = ClassWithMonitoredString(monitoredString)
    println(data.toJson())
    data.monitoredProperty.value = "obsChanged"
    println(data.toJson())
}

जो पैदावार में निम्नलिखित परिणाम:

{"monitoredProperty":"obsDefault"}
I changed from "obsDefault" to "obsChanged"!
{"monitoredProperty":"obsChanged"}

हालांकि आप कम जानकारी के बारे में जो संपत्ति बदल गया है, के रूप में आप की जरूरत नहीं है आसान पहुँच के लिए क्षेत्र का नाम है । इसके अलावा, आप को बदलने के लिए अपने डेटा संरचनाओं, के रूप में ऊपर उल्लेख किया है और नहीं हो सकता है वांछनीय हो सकता है या यहां तक कि संभव है. इसके अलावा, इस काम के लिए केवल तार के लिए अब है, भले ही एक हो सकता है इसे बनाने और अधिक सामान्य है, हालांकि. इसके अलावा, इस का एक बहुत आवश्यकता है बॉयलरप्लेट साथ शुरू करने के लिए. फोन पर साइट हालांकि, आप बस लपेटो करने के लिए वास्तविक मूल्य में एक कॉल करने के लिए obs. मैं निम्नलिखित बॉयलरप्लेट यह काम करने के लिए.

typealias OnChange = (before: String, after: String) -> Unit

@Serializable(with = MonitoredStringSerializer::class)
class MonitoredString(initialValue: String, var onChange: OnChange?) {
    var value: String = initialValue
        set(value) {
            onChange?.invoke(field, value)

            field = value
        }

}

fun obs(value: String, onChange: OnChange? = null) = MonitoredString(value, onChange)

object MonitoredStringSerializer : KSerializer<MonitoredString> {
    override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("MonitoredString", PrimitiveKind.STRING)

    override fun serialize(encoder: Encoder, value: MonitoredString) {
        encoder.encodeString(value.value)
    }

    override fun deserialize(decoder: Decoder): MonitoredString {
        return MonitoredString(decoder.decodeString(), null)
    }
}
2021-11-24 18:19:41

मैं वर्तमान में का पालन करें एक समान दृष्टिकोण है, लेकिन यह की तरह लगता है, यह बेहतर हो सकता है. मैं एक कदम आगे चले गए बनाने के लिए एक विधि monitoredString देता है जो एक MonitoredString और के बाद से इस समारोह का उपयोग करने के लिए इस, मैं नहीं है पारित करने के लिए onChange, मैं सिर्फ यह लिंक करने के लिए OnChange । नकारात्मक पक्ष होने के एक नमूदार "राज्य" वर्ग और फिर एक डेटा स्थानांतरण जा सकता है कि वर्ग धारावाहिक है दोहराव मॉडल के क्षेत्रों. लगता है केवल अच्छा समाधान प्राप्त होता है कि मैं क्या करना चाहते हैं, है व्याख्या करने के लिए @के साथ कुछ और तो उत्पन्न बॉयलरप्लेट का उपयोग कर KSP.
Jan Vladimir Mostert

अन्य भाषाओं में

यह पृष्ठ अन्य भाषाओं में है

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................

इस श्रेणी में लोकप्रिय

लोकप्रिय सवाल इस श्रेणी में