Inheritance 收集独特对象的最佳方法

Inheritance 收集独特对象的最佳方法,inheritance,kotlin,Inheritance,Kotlin,我试图只收集唯一的对象,然后将它们输出到CSV文件 下面的代码行吗?!还是有正确的方法 interface f { val s1: String val s2: String fun tot():Int } data class A(override val s1: String, override val s2:String, val sub_cost1: Int, val sub_cost2: Int) : f { override fun tot() :

我试图只收集唯一的对象,然后将它们输出到CSV文件 下面的代码行吗?!还是有正确的方法

interface f {
    val s1: String
    val s2: String
    fun tot():Int
}

data class A(override val s1: String, override val s2:String, val sub_cost1: Int, val sub_cost2: Int) : f {
    override fun tot() : Int { return sub_cost1 + sub_cost2}
}
data class B(override val s1: String, override val s2:String, val b_cost: Int, val area: Int) : f {
    override fun tot() : Int { return b_cost}
}
data class C(override val s1: String, override val s2:String, val c_cost: Int) : f{
    override fun tot() : Int { return c_cost}
}

fun main(args: Array<String>) {
    val s = mutableSetOf<f>()
    s.add(C("a0","b0", 1))
    s.add(C("a0","b0", 1)) // equal to first elem, must not be added!
    s.add(A("a1","a2", 2, 3))
    s.add(B("b1","b2", 5, 6))

    // to output into CSV file
    println("s1, s2, sub_cost1, sub_cost2, b.cost, c.cost, tot")
    for (i in s) { 
        when (i) {
            is A -> println("${i.s1}, ${i.s2}, ${i.sub_cost1}, ${ i.sub_cost2}, , , ${i.tot()}")
            is B -> println("${i.s1}, ${i.s2}, , , ${i.b_cost}, , ${i.tot()}")
            is C -> println("${i.s1}, ${i.s2}, , , , ${i.c_cost}, ${i.tot()}")
        }
    }
}
接口f{
val s1:字符串
val s2:字符串
fun tot():Int
}
数据类A(覆盖值s1:String,覆盖值s2:String,值sub_cost1:Int,值sub_cost2:Int):f{
override fun tot():Int{return sub_cost1+sub_cost2}
}
数据类B(覆盖值s1:String,覆盖值s2:String,值B_成本:Int,值区域:Int):f{
重写fun tot():Int{return b_cost}
}
数据类C(覆盖值s1:String,覆盖值s2:String,值C_成本:Int):f{
重写fun tot():Int{return c_cost}
}
趣味主线(args:Array){
val s=mutableSetOf()
s、 加上(C(“a0”、“b0”、1))
s、 添加(C(“a0”,“b0”,1))//等于第一个元素,不得添加!
s、 加上(A(“a1”、“a2”、2、3))
s、 加上(B)(“b1”、“b2”、5、6))
//输出到CSV文件
println(“s1、s2、次级成本1、次级成本2、b.成本、c.成本、tot”)
对于(i in s){
何时(i){
是->println(${i.s1}、${i.s2}、${i.sub_cost1}、${i.sub_cost2}、${i.tot()})
是B->println(${i.s1},${i.s2},${i.B_cost},${i.tot()}”)
是C->println(${i.s1},${i.s2},${i.C_cost},${i.tot()}”)
}
}
}
预期产出:

s1、s2、次级成本1、次级成本2、b_成本、c_成本、tot

a0,b0,1,1

a1、a2、2、3、5


b1、b2、5、5

是的,使用
集合来自动防止重复是很常见的。我认为它肯定算作“正确”,这里没有明显更好的建议

请注意,只有当集合可以判断它们是重复的时,这才起作用;因此,对象需要有一个合适的
equals()
方法的实现,或者需要给集合一个
比较器,比较器就是这样做的。在这种情况下,您使用的是
数据类
es,它会自动给您一个合适的
equals()
实现

使用
集合
还可以让阅读代码的人清楚地了解您的意图

(另一个优点是大多数实现可以非常快速地检查对象的存在与否。它们也有缺点:它们往往比简单的
列表
占用更多的内存,并且简单的实现没有一致或可预测的迭代顺序。但这些通常都不是问题——如果您对于有序迭代,您可以使用例如
LinkedHashSet

我可能会考虑在代码中更改的一件事是
when
;这要求代码的主要部分了解
f
的每个实现及其内部。最好的方法并不明显。如果您认为字符串处理与对象内部的联系比与CSV格式的联系更紧密,那么您就是crea但是,您可以向接口添加一个方法,该方法返回一个
字符串
(标准的
toString()
方法,或者一个方法,比如
toCSVLine()
),然后每个类都可以根据自己的需要实现它,主代码可以调用它,而不关心细节(或者如果CSV详细信息更好地保存在一起,那么
when
可能会更好。或者您可能会发现一种混合方法,其中
f
界面中的方法可以提供所需的所有信息,而无需了解任何实现情况。)

(另外,我将
f
interface大写。Kotlin(和Java)编码标准都以大写字母开头接口名称,就像类名一样。)