【问题标题】:Overriding unapply method覆盖 unapply 方法
【发布时间】:2013-09-17 11:36:54
【问题描述】:

我有一个来自库类的 案例,我想重写 unapply 方法以减少参数数量我需要传递以对其进行模式匹配.我这样做:

object ws1 {
  // a library class
  case class MyClass(a: Int, b: String, c: String, d: Double /* and many more ones*/)

  // my object I created to override unapply of class MyClass
  object MyClass {
    def unapply(x: Int) = Some(x)
  }

  val a = new MyClass(1, "2", "3", 55.0 /* and many more ones*/)
  a match {
    case MyClass(x /*only the first one is vital*/) => x  // java.io.Serializable = (1,2,3,55.0)
    case _ => "no"
  }
}

但我希望它只返回1。这有什么问题?

【问题讨论】:

    标签: scala


    【解决方案1】:
    case class MyClass(a: Int, b: String, c: String, d: Double /* and many more ones*/)
    object MyClassA {
       def unapply(x: MyClass) = Some(x.a)
    }
    
    val a = new MyClass(1, "2", "3", 55.0 /* and many more ones*/)
    
    a match {
        case MyClassA(2) => ??? // does not match
        case MyClassA(1) => a   // matches
        case _ => ??? 
    }
    

    您不能在MyClass 对象中定义您的自定义unapply 方法,因为它必须采用MyClass 参数,并且那里已经有一种这样的方法——一种为案例类自动生成的方法。因此,您必须在不同的对象中定义它(在这种情况下为MyClassA)。

    Scala 中的模式匹配获取您的对象并对其应用多个unapplyunapplySeq 方法,直到它获得具有与模式中指定的值匹配的值的Some
    MyClassA(1) 匹配a如果MyClassA.unapply(a) == Some(1).

    注意:如果我写了case m @ MyClassA(1) =>,那么m 变量的类型将是MyClass

    编辑:

    a match {
        case MyClassA(x) => x  // x is an Int, equal to a.a
        case _ => ??? 
    }
    

    【讨论】:

    • 为什么在 a 或 d 的情况下返回 Any?
    • 你能发布一个导致问题的sn-p吗?
    • @Grienders 它返回 Any 因为您的默认情况,它指定返回值“no”。由于一种情况返回 Int,另一种情况返回 String,因此匹配结果的最接近的公共超类是 Any。
    • @Shadowlands,为什么 b 返回字符串?
    • 我实际上有一个更复杂的类层次结构。我做了我需要做的一切。但它包含wrong number of arguments for pattern MyClass(a: Int, b: String, c: String, d: Double /* and many more ones*/)。一切都导入了,我什至导入了 MyClassA 的 unapply 方法,但还没有运气。你知道为什么吗?
    【解决方案2】:

    我会放弃重载的 unapply,只使用以下内容进行匹配:

    a match {
      case MyClass(x, _, _, _) => x  // Result is: 1
      case _ => "no"
    }
    

    编辑:

    如果您真的想避免多余的下划线,我认为您需要查看以下内容:

    a match {
      case x:MyClass => x.a
      case _ => "no"
    }
    

    【讨论】:

    • 这是我不想做的事情,这就是我决定覆盖 unapply 的原因。
    • 你为什么不想要这个?它不适合你怎么办?
    • 如果 x 是 Seq 或 List 怎么办,我必须再次进行模式匹配?
    • 您的意思是 x 是 List 而不是 MyClass?在这种情况下,使用:: 处理列表有特定的模式。如果您想要(仅)列表的第一个元素,如果它存在,则匹配:case x :: theRest => x
    猜你喜欢
    • 1970-01-01
    • 2018-06-21
    • 1970-01-01
    • 2016-03-06
    • 2018-03-27
    • 2014-05-27
    • 2014-01-04
    • 2021-11-11
    • 2010-11-16
    相关资源
    最近更新 更多