scala中基本类型的可选转换

时间:2016-12-02 03:18:24

标签: scala

我正在尝试支持框架的ID类型的抽象。示例:

object AmINecessary {
  case class StringConverter[T](op: String => T)
  implicit val toInt = new StringConverter[Int](_.toInt)
  implicit val toLong = new StringConverter[Long](_.toLong)
}

class Foo[ID] {
  // ID can be String, Long, or Int
  import AmINecessary._
  // If ID is string, return string, otherwise convert to ID
  def getID(id: String)(implicit c: StringConverter[ID] = null): ID = if (c == null) id.asInstanceOf[ID] else c.op(id)
}

然后用作:

val fooString = new Foo[String]
val fooLong = new Foo[Long]
val fooInt = new Foo[Int]


fooString.getID("asdf") // "asdf":String
fooLong.getID("1234") // 1234:Long
fooInt.getID("1234") // 1234:Int
fooInt.getID("asdf") // java.lang.NumberFormatException

这可以按预期工作。我的问题是:

  1. 使用可选的隐式,默认为null,然后分支就感觉。什么是scala方法来实现这一目标?
  2. 是否真的有必要将字符串的隐式转换写入long或int?

2 个答案:

答案 0 :(得分:1)

我认为最好的选择是简单地添加隐式StringConverter[String]并删除默认的null值。 这样,您的fooString可以在不冒任何其他类型ClassCastException的情况下工作。

object AmINecessary {
  case class StringConverter[T](op: String => T)
  implicit val toInt = new StringConverter[Int](_.toInt)
  implicit val toLong = new StringConverter[Long](_.toLong)
  implicit val idConverter = new StringConverter[String](identity)
}

class Foo[ID] {
  import AmINecessary.StringConverter

  def getID(id: String)(implicit c: StringConverter[ID]): ID = c.op(id)
}

关于您的问题2,类型类方法不是非常必要(但请注意,此处没有隐式转换)。你也可以这样做:

abstract class Foo[ID] {
  def getID(id: String): ID
}

class FooInt extends Foo[Int] {
  def getID(id: String) = id.toInt
}

class FooLong extends Foo[Long] {
  def getID(id: String) = id.toLong
}

class FooString extends Foo[String] {
  def getID(id: String) = id
}

答案 1 :(得分:0)

1)关于隐式默认为null,你可以:

object Unsafe {
  implicit val toT[T] = new StringConverter[T](_.asInstanceOf[T])
}

2)这似乎不是一个好主意。首先,因为你隐藏了asInstanceOf,这是不安全的操作(潜在的运行时异常)。其次,转换越明确 - 越好。

如果您期望进行一些复杂的转换 - 最好从getID方法返回选项:

def getId[T](id: String)(converter: Option[StringConverter] = None) = converter.map(_.op(id))

但是,默认参数也不是最好的方法。我会坚持编译时错误,要求用户编写自己的转换器或明确地执行asInstanceOf

在你的具体情况中asInstanceOf没有多大意义,因为它唯一适用的类型是String,如getId[String],那么调用getId的重点是什么呢? / p>