【问题标题】:Intersect two sets, of a class and of a derived class [duplicate]相交两个集合,一个类和一个派生类[重复]
【发布时间】:2017-10-06 08:51:23
【问题描述】:

我有两组,其中一组列出了派生类的实例。创建的集合类型不在我的控制范围内,我无法确保两者都是Set[A]set23 用于我需要其类型为Set[B] 的其他上下文中。我想相交:

case class A(name: String)
class B(name: String) extends A(name)

val set12 = Set(new A("1"), new A("2"))
val set23 = Set(new B("2"), new B("3"))

set12 intersect set23 // does not work

错误是:

类型不匹配; 找到:scala.collection.immutable.Set[B]

必需:scala.collection.GenSet[A]

注意:B <: a trait genset>

我知道Set 不是协变的,是否有一些干净的解决方法而不重建集合?以下作品,但我不想使用asInstanceOf

set12 intersect set23.asInstanceOf[Set[A]]

【问题讨论】:

    标签: scala collections set covariance


    【解决方案1】:

    当您将集合创建为 Set(new A("1"), new A("2")) 时,它会将类型 Set[A] 分配给结果值。 当您将集合创建为 Set(new B("2"), new B("3")) 时,它会将类型 Set[B] 分配给结果值。

    因此,结果集是不同类型的,不能相交。但是,如果您按如下方式初始化变量:

    val set12: Set[A] = Set(new A("1"), new A("2"))
    val set23: Set[A] = Set(new B("2"), new B("3"))
    

    然后,您自己分配类型。由于结果值具有相同的类型,因此您可以相交并执行其他操作。

    例如,您可以像下面这样使用intersect

    val as: Set[A] = set12 intersect set23  // gives empty set as intersection
    

    在上面的示例中,生成的交集是空的,因为它们没有相同的对象。

    要实现成功比较,您还应该重写类的equals 方法。在您的情况下,仅覆盖 A 就足够了。 以下是一种不推荐但可行的方式(因为不鼓励扩展案例类):

    case class A(name: String) {
      override def equals(obj: scala.Any): Boolean = obj match {
        case A(x) => x.equals(name)
        case _ => false
      }
    }
    
    class B(name: String) extends A(name)
    
    val set12: Set[A] = Set(new A("1"), new A("2"))
    val set23: Set[A] = Set(new B("2"), new B("3"))
    
    val as: Set[A] = set12 intersect set23  // gives A(2) as intersection
    println(s"as = ${as}")
    

    【讨论】:

    • “但如果你按如下方式初始化变量:”我试图在我的问题中写下这是我无法做到的。在需要 B 类型的其他上下文中,我需要 set23。
    • "结果交集为空" 你是对的,我把代码简化了。我已将 A 更改为案例类 - 我知道从案例类派生是不好的做法,但就这个问题而言,这是确保 equals 被覆盖的最短方法。
    • case class 示例仅用于问题的目的,它适用于此目的。很抱歉,但是通过扩展如何正确覆盖 equals 我并没有更接近实现我的目标,答案的核心部分仍然是避免如何交叉两个需要不同类型的集合的问题。
    • 在对您的评论进行了一些研究之后,我认为即使它们具有某种协变或逆变关系,也无法比较两种不同的类型。详情请见link
    猜你喜欢
    • 2017-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-19
    • 1970-01-01
    • 2021-05-22
    • 1970-01-01
    相关资源
    最近更新 更多