【问题标题】:Handling lists of two different types with same code using functional programming in kotlin在 kotlin 中使用函数式编程处理具有相同代码的两种不同类型的列表
【发布时间】:2018-10-02 06:54:42
【问题描述】:

我有两个不同类型的列表 list1 和 list2 。我有一个对列表执行相同操作的方法。

如果我使用的是 Any 类型的列表,我将使用 lambdas,而我无法以 (it.prop1) 的形式访问该属性。

是否有任何解决方案可以避免 lambdas 出现这个问题?

val list1: List<Student> = ..
val list2: List<Teacher> = ..

list1.filter {
    school.contains(it.prop1) }
.forEach {
    total +=  it.prop2.toLong()
}

list2.filter {
    school.contains(it.prop1) }
.forEach {
    total +=  it.prop2.toLong()
}

谢谢。

【问题讨论】:

  • StudentTeacher 是否具有公开 prop1prop2 的公共接口?
  • 不,它们没有实现通用接口
  • 那么你可以添加一个接口并使用相同的代码处理list1list2

标签: kotlin functional-programming


【解决方案1】:

试试这个:

object Test {

    private fun isContains(school: Set<Int>, any: Any) = when (any) {
        is Student -> school.contains(any.prop1)
        is Teacher -> school.contains(any.prop1)
        else -> false
    }

    private fun value(any: Any) = when (any) {
        is Student -> any.prop2
        is Teacher -> any.prop2
        else -> throw NoWhenBranchMatchedException("any should be Student or Teacher")
    }

    @JvmStatic
    fun main(args: Array<String>) {
        val school = setOf(1, 2)
        val list = listOf(Student(1, 1), Student(2, 2), Student(3, 3), Teacher(1, 1), Teacher(2, 2), Teacher(3, 3))

        val total = list.filter {
            isContains(school, it)
        }.map {
            value(it)
        }.sum()

        println("Total: $total")
    }

    private class Student(val prop1: Int, val prop2: Int)

    private class Teacher(val prop1: Int, val prop2: Int)
}

【讨论】:

    【解决方案2】:

    您可以使用Type Checks and Casts

    class Student(val prop1:Int, val prop2:Int)
    class Teacher(val prop1:Int, val prop2:Int)
    val list : List<Any> = listOf(Student(1,1),Student(2,2),Student(3,3),Teacher(1,1),Teacher(2,2),Teacher(3,3))
    var total : Long = 0
    val school : Array<Int> = arrayOf(1,2)
    list.filter{
        if(it is Student)
        {
            school.contains((it as Student).prop1)
        }
        else if(it is Teacher)
        {
            school.contains((it as Teacher).prop1)
        }
        else
        {
            false
        }
    }.forEach{
        if(it is Student)
        {
            total += (it as Student).prop2.toLong()
        }
        else if(it is Teacher)
        {
            total += (it as Teacher).prop2.toLong()
        }
    
    }
    println(total)  //print 6 in this example
    

    这很难看。最好让StudentTeacher要么继承公共超类,要么实现公共接口

    【讨论】:

      【解决方案3】:

      据我所知,你不能。您可以利用通用接口。

      例如:

      interface Human{
          val age: Int
      }
      
      class Student(override val age: Int): Human
      
      class Teacher(override val age: Int, val salary: Double):Human
      
      fun x(){
          val list1: List<Student> = ...
          val list2: List<Teacher> = ...
          val school: List<Human> = ...
      
          val result = school
              .filter { it is Student }
              .sumBy { it.age}
      
          val result2 = school
              .filter { it is Teacher }
              .sumBy { it.age }
      
      }
      

      【讨论】:

        猜你喜欢
        • 2019-07-14
        • 1970-01-01
        • 2020-01-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-12-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多