避免重复相同的逻辑

问题描述 投票:0回答:1

我有以下数据类。

sealed class ExampleDto

object Type1ExampleDto : ExampleDto()

object Type2ExampleDto : ExampleDto()

data class Type3ExampleDto(val name: Int, val age: Int) : ExampleDto()

data class Type4ExampleDto(val name: Int, val age: Int) : ExampleDto()

data class Type5ExampleDto(val email: String) : ExampleDto()

data class Type6ExampleDto(val name: Int, val age: Int, val email: String) : ExampleDto()

特别是: Type3ExampleDto, Type4ExampleDtoType6ExampleDto 有一些共同的字段,但对我的业务逻辑来说,重要的是要区别于 类型 纵使 Type3ExampleDtoType4ExampleDto 是相同的,我必须知道我是否在。第三类4型 case)。

在我的一个方法中,我有以下的调用。

when (type) {
            is Type3ExampleDto -> myMethod(type.vote, type.text)
            is Type4ExampleDto -> myMethod(type.vote, type.text)
            is Type6ExampleDto -> myMethod(type.vote, type.text)
            else -> null
        }

我发现我在三个情况下都做了同样的操作 而且重复了同一行... ...

这样做是有意义的 Type3ExampleDto, Type4ExampleDtoType6ExampleDto 某种接口的实现,只是因为 只是 在这一点上,我在做这种丑陋的重复?

如果三个dtos都实现了下面的接口。

interface MyInterface{
fun getVote() : Int
fun getText() : String

}

我可以写。

if (type is MyInterface) {
    myMethod(type.getVote(), type.getText())
}

那么,为了解决这个孤立重复的问题,建立这个接口可以接受吗?

谅谅

kotlin coding-style
1个回答
1
投票

注意,你可以像这样做得更干净。

interface NameAndAgeDto {
    val name: Int
    val age: Int
}

data class Type3ExampleDto(override val name: Int, override val age: Int) : ExampleDto(), NameAndAgeDto

if (type is NameAndAgeDto) {
    myMethod(type.name, type.age)
}

是否 "可以接受 "是个问题。在我看来很好。


0
投票

你可以改变你的模型,让你的逻辑基于 行为而非继承. 这种建模方式是基于(但不完全是)以下原则: 策略设计模式.

interface HasName {
    val name: String
}

interface HasAge {
    val age: Int
}

interface HasEmail {
    val email: String
}

object Type1

object Type2

data class Type3(
        override val name: String,
        override val age: Int
) : HasName, HasAge

data class Type4(
        override val name: String,
        override val age: Int
) : HasName, HasAge

data class Type5(
        override val email: String
) : HasEmail

data class Type6(
        override val name: String,
        override val age: Int,
        override val email: String
) : HasName, HasAge, HasEmail

// Then you can pass any object to it.
fun main(obj: Any) {
    // Koltin type-casts it nicely to both interfaces.
    if (obj is HasName && obj is HasAge) {
        myMethod(text = obj.name, vote = obj.age)
    }
}

fun myMethod(vote: Int, text: String) {

}

如果你仍然希望所有类型都属于某个父类型,你可以使用 标记界面 没有任何方法)。

interface DTO

interface HasName {
    val name: String
}

interface HasAge {
    val age: Int
}

interface HasEmail {
    val email: String
}

object Type1 : DTO

object Type2 : DTO

data class Type3(
        override val name: String,
        override val age: Int
) : HasName, HasAge, DTO

data class Type4(
        override val name: String,
        override val age: Int
) : HasName, HasAge, DTO

data class Type5(
        override val email: String
) : HasEmail, DTO

data class Type6(
        override val name: String,
        override val age: Int,
        override val email: String
) : HasName, HasAge, HasEmail, DTO

// Here, it is DTO instead of Any
fun main(obj: DTO) {
    if (obj is HasName && obj is HasAge) {
        myMethod(text = obj.name, vote = obj.age)
    }
}

并使用 sealed 代替标记 interface 如果您需要 枚举式. 在这种情况下: when 在...上 sealed class 穷尽所有选项,但不包括 null ->.

© www.soinside.com 2019 - 2024. All rights reserved.