2011-04-25 91 views
2

我有以下方法:斯卡拉 - 从泛型类型构造方法名称?

def toNumber[T <: AnyVal](value:String, default:T)(implicit n: Numeric[T]):T = { 
    val str = value.trim 
    var s = n.zero 
    if (value.trim.isEmpty) { 
     default 
    } else { 
     if (default.isInstanceOf[Long]) 
     s = n.plus(n.zero,str.toLong.asInstanceOf[T]) 
     else if (default.isInstanceOf[Int]) 
     s = n.plus(n.zero,str.toInt.asInstanceOf[T]) 
    } 
    s 
    } 

是否有可能,所以它看起来在T(如int,long等等)的类型以某种方式简化这一点,并使用它来调用权“到”法(如toInt,toLong等)?

作为奖励的问题,我可以以某种方式限制吨至只是int和long,而不是任何AnyVal的子类?

感谢, 约翰

回答

10

如果你想限制T具体数字的情况下,它可能是一个好主意,提供自己的类型类(从而提供一个答案,你最初的问题):

trait Natural[T] { def from(s : String) : T } 
implicit object IntNatural = new Natural[Int] { 
    def from(s : String) = s.toInt 
} 
implicit object LongNatural = new Natural[Long] { 
    def from(s : String) = s.toLong 
} 

然后你的方法:

def toNumber[T : Natural](value : String, default : T) : T = 
    if (value.trim.isEmpty) 
    default 
    else 
    implicitly[Natural[T]].from(value.trim) 


不过,我会亲自重新写这个方法的签名:

def natural[T : Natural](value : String) : Option[T] 

然后用户将在使用现场使用getOrElse default。例如:

natural[Int]("42") getOrElse 23 
+1

这可能是最好的解决方案,尽管我可能会为类型类使用不同的名称,因为Integral已经是Scala类型类。 – derekjw 2011-04-25 16:35:44

+0

另外,我有一个只包含隐含IntIntegral性状IntegralImplicits,然后具有延伸IntegralImplicits,也包含隐含LongIntegral对象积分。然后,当用户呼叫'toNumber(“42”)'时,默认为选项[Long]。如果用户调用'toNumber [Int](“42”)'它是一个选项[Int]。 – derekjw 2011-04-25 16:41:50

+0

同意'积分' - 已经改为'自然'(尽管有一点数学上的谎言) – 2011-04-25 17:13:25