Scala 在抽象类扩展中具有相同字段的两个不同对象的排序列表



假设我有:

object test{
abstract class Base 

然后是扩展 Base 的两个案例类 alpha 和 beta,这样写:

case class alpha(num: Int, other: String) extends Base
case class beta(num:Int, other_two: String) extends Base

然后假设我有一个基本对象列表,List[Base].

其中一些对象是 alpha,有些是 beta。我想按字段num(alpha 和 beta 对象之间的公共字段)对它们进行排序。

根据我阅读/谷歌搜索的内容,每个人和他们的祖母建议执行以下操作:

val i: List[Base] =  List(alpha(4,"test"),beta(2,"test_two")).sortby(_.num)

但是,这不起作用。 工作原理是:

val j: List[Base] =List(alpha(4,"test"),beta(2,"test_two")).sortWith(num(_) < num(_)) 
} 

我的问题是为什么前者不起作用,为什么后者有效?

您可以在基类中声明子类应该具有num值:

abstract class Base {
val num: Int
}

然后使用第二个变体

val i: List[Base] =  List(alpha(4,"test"),beta(2,"test_two")).sortBy(_.num)

您的第一个示例不起作用,因为它没有.num成员Base。尽管List的所有元素可能都有.num成员,但编译器已被告知将它们视为类型Base_.num

因此无效。仅当方法num()存在时,sortWith()示例才有效。像这样的东西。

def num(x: Base): Int = x match {
case a: alpha => a.num   // BTW, class names should be capitalized
case b: beta  => b.num
case _ => 0
}

现在,第二个示例可以编译并工作,因为num()方法正在确定类型并提取.num成员(如果存在)。但如果是这种情况,那么你的第一个例子也可以工作。

val i: List[Base] = List(alpha(4,"test"),beta(2,"test_two")).sortBy(num)

按照 @Harald 的建议,如果按如下方式修改提供的函数,则sortWith方法将起作用:

abstract class Base {
val num: Int
}
case class Alpha(num: Int, other: String) extends Base
case class Beta(num: Int, other_two: String) extends Base
List(Alpha(4, "test"), Beta(2, "test_two")).sortWith(_.num < _.num)
res1: List[Product with Serializable with Base] = List(Beta(2,test_two), Alpha(4,test))
// OR
List(Alpha(4, "test"), Beta(2, "test_two")).sortWith((x, y) => x.num < y.num)
res2: List[Product with Serializable with Base] = List(Beta(2,test_two), Alpha(4,test))

最新更新