【问题标题】:How to write scala matcher for class?如何为类编写 scala 匹配器?
【发布时间】:2012-03-01 19:43:41
【问题描述】:

假设我有以下代码

def get[T](name:String)(implicit mf:ClassManifest[T]):T = mf.erasure match {
     case classOf[Boolean] => obj.getBoolean(name)
     case classOf[Int] => obj.getInt(name)
   }

现在代码不起作用,因为 classOf[Int] 是无效的匹配值。

【问题讨论】:

  • 如果你只需要值类型,看看 ClassManifest, def fromClass[T](clazz: JClass[T]): ClassManifest[T] = clazz match { case java.lang.Byte. TYPE => Byte.asInstanceOf[ClassManifest[T]] ....

标签: scala pattern-matching


【解决方案1】:

您几乎肯定应该研究在类对象上使用清单和匹配的替代方法。在这种情况下,类型类将提供更简洁的解决方案,

// Assuming that Store is the type of obj ...

trait Get[T] { def get(s : Store, name : String) : T }
implicit val getBoolean = new Get[Boolean] {
  def get(s : Store, name : String) : Boolean = s.getBoolean(name)
}
implicit val getInt = new Get[Int] {
  def get(s : Store, name : String) : Int = s.getInt(name)
}

def get[T](name : String)(implicit inst : Get[T]) : T = inst.get(obj, name)

使用此实现,如果您要求不支持的类型,而不是在运行时收到匹配错误,而是会收到静态编译时错误。

另请注意,作为一种在擦除之前应用的编译时解析机制,这种技术比在运行时擦除后的匹配要精确得多。例如,使用这种技术,我们可以区分 List[Int]List[String] 情况,而它们将等同于运行时测试。

【讨论】:

    【解决方案2】:

    这对我有用:

    val mf = //some manifest
    mf.erasure match {
      case c if c == classOf[String] => "string!"
      case c if c == classOf[Int] => "int!"
      case c if c == classOf[Boolean] => "bool!"
      //...
    }
    

    【讨论】:

    • 注意:这种方法对于琐碎的事情来说很好,但迈尔斯的回答强调了一个重要的点:编译时错误比运行时错误更容易检测到。如果您在 classOf[SomethingElse] 上尝试,这种方式会给您一个运行时错误,而如果您尝试 get[SomethingElse] 如果没有可用的隐式,则使用隐式会给您一个编译器错误。
    猜你喜欢
    • 1970-01-01
    • 2016-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-06
    • 1970-01-01
    • 2013-05-26
    相关资源
    最近更新 更多