如何在Scala中初始化Type变量?

时间:2018-07-20 13:36:08

标签: scala types nullable classtag

我是scala的新手,对这个愚蠢的问题感到抱歉。 我想从此Scala代码中删除return语句(我的实际情况比这复杂得多)

def readValue[Type](value: Any)(implicit tag: ClassTag[Type]): Type = {

    if (value == null) { 
      return null.asInstanceOf[Type] 
    } else {
      if (classOf[URL].isAssignableFrom(tag.runtimeClass)) {
        return new URL(value.toString).asInstanceOf[Type]
      }
      if (classOf[URI].isAssignableFrom(tag.runtimeClass)) {
        return new URI(value.toString).asInstanceOf[Type]
      }
      null.asInstanceOf[Type]
    }
}

这就是为什么我要存储Type实例的返回值,例如:

def readValue[Type](value: Any)(implicit tag: ClassTag[Type]): Type = {

    var retVal:Type = null
    if (value == null) { 
       // retVal=...
    } 
    else { 
       // if cond: retVal=...
    }
    retVal
}

以上解决方案无法编译。 我如何初始化类型为Type的变量?

2 个答案:

答案 0 :(得分:2)

if-else表达式,而不仅仅是scala中的声明

def readValue[Type](value: Any)(implicit tag: ClassTag[Type]): Type = {
    if (value == null) { 
      null.asInstanceOf[Type] 
    } else if (classOf[URL].isAssignableFrom(tag.runtimeClass)) {
      new URL(value.toString).asInstanceOf[Type]
    } else if (classOf[URI].isAssignableFrom(tag.runtimeClass)) {
      new URI(value.toString).asInstanceOf[Type]
    } else {
      null.asInstanceOf[Type]
    }
}

还要注意,classOf[A].isAssignableFrom(classOf[B])意味着类型b的值B可以向下转换为b.asInstanceOf[A],而不是相反。如果为classOf[URL].isAssignableFrom(tag.runtimeClass),则可以将类型Type的值强制转换为URL反之亦然

此外,如果将参数Type限制为Type >: Null,则您的代码将起作用。

答案 1 :(得分:2)

也许是这样的:

 Option(value)
   .map { _.toString }
   .map { v =>  tag.runtimeClass.getConstructor(v.getClass).newInstance(v) }
   .map { _.asInstanceOf[Type] }
   .orNull

或者如果您希望避免反射,可以这样做:

val contructors: Map[Class[_], String => Any] = Map(
  classOf[URL] -> { s => new URL(s) }
  classOf[Uri] -> { s => new URI(s) }
}

Option(value)
 .map { _.toString }
 .map { constructors(tag.runtimeClass).apply(_) }
 .map { _.asInstanceOf[Type] }
 .orNull