Использование asInstanceOf для преобразования Any в Double

У меня есть функция, которая принимает переменное количество аргументов. Первая - это String, а остальные - числа (Int или Double), поэтому я использую Any * для получения аргументов. Я хотел бы рассматривать числа равномерно как Doubles, но я не могу просто использовать asInstanceOf [Double] для числовых аргументов. Например:

 val arr = Array("varargs list of numbers", 3, 4.2, 5)
 val d = arr(1).asInstanceOf[Double]

дает:

 java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Double

Есть ли способ сделать это? (Функция должна содержать все числа).

Ответ 1

Scala asInstanceOf - это его имя для кастинга. Кастинг не преобразуется.

То, что вы хотите, может быть выполнено следующим образом:

val mongrel = List("comment", 1, 4.0f, 9.00d)
val nums = mongrel collect { case i: Int => i case f: Float => f case d: Double => d }
val sumOfNums = nums.foldLeft(0.0) ((sum, num) => sum + num)

Ответ 2

Вот небольшое облегчение ответа Рэндалла:

val mongrel = List("comment", 1, 4.0f, 9.00d)
val nums = mongrel collect { case i: java.lang.Number => i.doubleValue() }
val sumOfNums = nums.sum

Соответствие для любого номера оказывается немного сложным в Scala, см. здесь для другого способа сделать это.

Ответ 3

Когда вам нужно обрабатывать разные типы, вам следует избегать их кастования и вместо этого использовать сопоставление шаблонов. Чтобы добавить все элементы Double и Int в массив, вы можете использовать:

val array = Array("varargs list of numbers", 3, 4.2, 5)

array.foldLeft(0.0){ 
  case (s, i: Int) => s + i
  case (s, d: Double) => s + d
  case (s, _) => s
}

Соответствие шаблону позволяет вам обрабатывать каждый отдельный тип отдельно и избегать запуска в ClassCastExceptions.

Ответ 4

Отступив на мгновение, может быть проще, чтобы функция приняла Double* вместо Any*?

scala> def foo(str: String, nums: Double*) { 
    nums foreach { n => println(s"num: $n, class:   ${n.getClass}") } 
}
foo: (str: String, nums: Double*)Unit

scala> foo("", 1, 2.3)
num: 1.0, class: double
num: 2.3, class: double