Kotlin中的类共同行为和不可变性

huangapple go评论64阅读模式
英文:

Classes common behavior + immutability in Kotlin

问题

以下是您提供的代码的翻译部分:

有没有一种更不可变的方式来实现以下内容

抽象类 Abstract {
    抽象属性 general1: String
    抽象属性 counter: Int // 不想在这里使用 var

    fun sumCounter(value: Int) {
        counter += value
    }
}

数据类 A (
    val a1: String,

    覆盖属性 general1: String,
    覆盖属性 counter: Int = 0,
): Abstract()

数据类 B (
    val b1: String,
    val b2: String,

    覆盖属性 general1: String,
    覆盖属性 counter: Int = 1,
): Abstract()

fun <T : Abstract> doSomething(obj: T) {
    //...
    obj.sumCounter(10) // 我想要:val newObj = obj.sumCounter(10)


    println(obj) // A(a1=a1, general1=general1, counter=10)
                 // B(b1=b1, b2=b2, general1=general1, counter=11)
    //...
}

fun myMain() {
    val a = A("a1", "general1")
    doSomething(a)

    val b = B("b1", "b2", "general1")
    doSomething(b)
}

请注意,代码中包含一些HTML编码字符(例如 <"),这些字符可能需要根据您的需求进一步处理。如果您有其他问题或需要进一步的帮助,请告诉我。

英文:

Is there a way to achieve the following but in a more immutable way?

abstract class Abstract {
    abstract val general1: String
    abstract var counter: Int // Don't want to use var here

    fun sumCounter(value: Int) {
        counter += value
    }
}

data class A (
    val a1: String,

    override val general1: String,
    override var counter: Int = 0,
): Abstract()

data class B (
    val b1: String,
    val b2: String,

    override val general1: String,
    override var counter: Int = 1,
): Abstract()

fun <T : Abstract> doSomething(obj: T) {
    //...
    obj.sumCounter(10) // I want: val newObj = obj.sumCounter(10)


    println(obj) // A(a1=a1, general1=general1, counter=10)
                 // B(b1=b1, b2=b2, general1=general1, counter=11)
    //...
}

fun myMain() {
    val a = A("a1", "general1")
    doSomething(a)

    val b = B("b1", "b2", "general1")
    doSomething(b)
}

It could be some Kotlin trick, functional approach, or design pattern to avoid creating the same methods in A and B. But I don't want to use reflections or convert to json and back.

答案1

得分: 2

这是我能找到的最接近的内容:

这是我能找到的最接近的内容

接口 Abstract<out T: Abstract<T>> {
    val general1: String
    val counter: Int // 不想在这里使用 var
    fun copy(newCounter: Int): T

    fun sumCounter(value: Int): T = copy(newCounter = counter + value)
}

数据类 A (
    val a1: String,

    override val general1: String,
    override val counter: Int = 0,
): Abstract<A> {
    override fun copy(newCounter: Int): A = copy(counter = newCounter)
}

数据类 B (
    val b1: String,
    val b2: String,

    override val general1: String,
    override val counter: Int = 1,
): Abstract<B> {
    override fun copy(newCounter: Int): B = copy(counter = newCounter)
}

fun <T : Abstract<T>> doSomething(obj: T) {
    //...
    val newObj = obj.sumCounter(10)

    println(newObj) // A(a1=a1, general1=general1, counter=10)
    // B(b1=b1, b2=b2, general1=general1, counter=11)
    //...
}

fun main(args: Array<String>) {
    val a = A("a1", "general1")
    doSomething(a)

    val b = B("b1", "b2", "general1")
    doSomething(b)
}

您仍然需要将 copy() 方法复制到每个子类中。

英文:

This is, unfortunately, the closest I got:

interface Abstract&lt;out T: Abstract&lt;T&gt;&gt; {
    val general1: String
    val counter: Int // Don&#39;t want to use var here
    fun copy(newCounter: Int): T

    fun sumCounter(value: Int): T = copy(newCounter = counter + value)
}

data class A (
    val a1: String,

    override val general1: String,
    override val counter: Int = 0,
): Abstract&lt;A&gt; {
    override fun copy(newCounter: Int): A = copy(counter = newCounter)
}

data class B (
    val b1: String,
    val b2: String,

    override val general1: String,
    override val counter: Int = 1,
): Abstract&lt;B&gt; {
    override fun copy(newCounter: Int): B = copy(counter = newCounter)
}

fun &lt;T : Abstract&lt;T&gt;&gt; doSomething(obj: T) {
    //...
    val newObj = obj.sumCounter(10)


    println(newObj) // A(a1=a1, general1=general1, counter=10)
    // B(b1=b1, b2=b2, general1=general1, counter=11)
    //...
}

fun main(args: Array&lt;String&gt;) {
    val a = A(&quot;a1&quot;, &quot;general1&quot;)
    doSomething(a)

    val b = B(&quot;b1&quot;, &quot;b2&quot;, &quot;general1&quot;)
    doSomething(b)
}

You still need to duplicate the copy() method into each sub-class.

huangapple
  • 本文由 发表于 2023年4月16日 23:28:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/76028647.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定