【问题标题】:Override toString behavior for Option[_] in scala覆盖 Scala 中 Option[_] 的 toString 行为
【发布时间】:2013-12-14 18:22:36
【问题描述】:

我希望只看到 Option 的值(如果它不是 None),而不是下面的附加 Some() 噪音:

List((Some(OP(_)),Some(share),3), (Some(OP(D)),Some(shaara),4), (Some(OP(I)),Some(shaaee),4))

现在,我可以为 List[Option[_]] 编写一个处理此问题的方法。但是还有许多其他结构中会出现 Options - 所以这种显式寻址每个结构的方法很麻烦。

由于隐含的优先级较低,以下代码将被忽略:

  implicit def toString(myopt : Option[_]) = if (myopt == None) "None" else myopt.get

令人担忧的是 - 尽管实现了例如 toString(List[Option_]]) 方法以所需的方式处理此问题,但这仍然是一次性的。一个

Map[Option,Option]  =>     def toString(Map[Option,Option]) = { .. }

看来我们仍然需要为每个集合类型实现一个显式的 toString()..

【问题讨论】:

    标签: scala scala-option


    【解决方案1】:

    我猜你不能覆盖toString 的这种行为,但你可以使用scalaz 中的shows(和show)方法。您可以覆盖这些方法的行为:

    import scalaz._, Scalaz._
    val l = List(1.some, none, 3.some, 4.some, none, 6.some)
    
    l.shows
    // res0: String = [Some(1),None,Some(3),Some(4),None,Some(6)]
    
    implicit def optionShow[T: Show]: Show[Option[T]] =
      Show.show{ _.map{_.show}.getOrElse(Cord("<none>")) }
    
    l.shows
    // res1: String = [1,<none>,3,4,<none>,6]
    

    它适用于Show 的所有类型:

    1.some.node(none.node(2.some.leaf)).drawTree
    // 1
    // |
    // `- <none>
    //    |
    //    `- 2
    
    Map(1.some -> 2.some, none[Int] -> 3.some).shows
    // Map[1->2, <none>->3]
    

    【讨论】:

    • 我正在更新问题,以便更清楚地说明跨各种数据结构的问题。
    • 推断是show()可以处理嵌套数据结构?我没有用过scalaz,但会尝试一下。
    • @javadba:对于泛型类Show 以泛型方式实现。所以Show[List[T]] 需要Show[T]。请注意,您必须为所有类实现Show(在最简​​单的情况下,它将是implicit myShow: Show[MyClass] = Show.showA)。
    【解决方案2】:

    好吧,我只想写一个类似于你的隐式包装器。

    class OW[T](val option : Option[T]) {
      override def toString = if (option.isEmpty) "None" else option.get.toString
    }
    

    然后,当我想要漂亮的 toString 时,我只需将任何集合映射到 OW 的实例。

    println(List(Some(3), Some("Hello"), None).map(new OW(_)))
    

    打印:List(3, Hello, None)

    真的没有更好的方法。

    【讨论】:

    • 如果您这样做,您不妨映射函数本身:.map(toString)。包装类似乎没有必要......
    • 这取决于用例。我有一个程序,我希望 ListView 显示与 toString 方法不同的字符串。所以我将这些元素包装在类似 OW 的东西中,然后将其传递给ListView。但是对于上面的这个例子,你是对的。
    【解决方案3】:

    以下处理想到的案例:

      def show(obj: Any) : String = {
        obj match {
          case o: Option[_] =>
            if (o == None) {
              "<none>"
            } else {
              show(o.get)
            }
          case i: Iterable[_] =>
            i.map(show).mkString("[", ",", "]")
          case m: Map[_, _] =>
            m.map {
              case (a, b) => List(show(a), show(b)).mkString(":")
            }.mkString("{", ",", "}")
          case e: Enumeration =>
            e.toString
          case c : Product if !c.getClass.getMethods.map(_.getName).contains("copy$default$2") =>
            c.toString
          case t: Product =>
            t.productIterator.map(a => show(a)).mkString("(", ",", ")")
          case _ =>
            if (obj.isInstanceOf[AnyRef])
              obj.asInstanceOf[AnyRef].toString
            else
              "" + obj
        }
      }
    

    我选择对此进行编码以避免添加 scalaz 依赖项(假设他们的 Show 类支持类似的功能)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多