3.5.3 Слабое соответствие В некоторых ситуациях Scala использует более общее отношение соответствия.Тип S слабо соответствует типу T, написанному S <: <sub>w T, если S <: T или оба S и T являются типами примитивных чисел и S предшествует T в следующем порядке.</p>
- Байт <: <sub>w Short
- Byte <: <sub>w Символ
- Short <: <sub>w Int
- Int <: <sub>w Long
- Long <: <sub>w Float
- Float <:<sub> w Double
Слабая наименьшая верхняя граница - это наименьшая верхняя граница в отношении слабого соответствия.
Где это используется?С одной стороны, он определяет тип if
выражений:
Тип условного выражения - это слабая наименьшая верхняя граница (§3.3.3) типов e2 и e3
В Scala 2.7.x это будет иметь тип AnyVal
с наименьшим верхним пределом Int
и Double
.В 2.8.x он печатается как Double
.
scala> if (true) 1 else 1d
res0: Double = 1.0
Аналогично:
scala> try { 1 } catch { case _ => 1.0 }
res2: Double = 1.0
scala> (new {}: Any) match { case 1 => 1; case _ => 1.0 }
res6: Double = 1.0
scala> def pf[R](pf: PartialFunction[Any, R]): PartialFunction[Any, R] = pf
pf: [R](pf: PartialFunction[Any,R])PartialFunction[Any,R]
scala> pf { case 1 => 1; case _ => 1d }
res4: PartialFunction[Any,Double] = <function1>
Другое место, где он используется, находится в выводе типа:
scala> def foo[A](a1: A, a2: A): A = a1
foo: [A](a1: A,a2: A)A
scala> foo(1, 1d)
res8: Double = 1.0
scala> def foos[A](as: A*): A = as.head
foos: [A](as: A*)A
scala> foos(1, 1d)
res9: Double = 1.0
А также для простого числового расширения:
Числовое расширение.Если e имеет примитивный тип чисел, который слабо соответствует (§3.5.3) ожидаемому типу, он расширяется до ожидаемого типа, используя один из методов преобразования чисел 6.26 Неявные преобразования 97 toShort, toChar, toInt, toLong, toFloat, toDoubleопределено в §12.2.1.ожидаемый тип - это примитивный числовой тип Byte, Short или Char, а выражение e - это целочисленный литерал, подходящий в диапазоне этого типа, он преобразуется в тот же литерал в этом типе.
scala> 1: Double
res10: Double = 1.0
ОБНОВЛЕНИЕ
Как указал Дэниел, спецификация неверна в отношении того, какие типы имеют слабую совместимость.Давайте спросим сам компилятор:
scala> :power
** Power User mode enabled - BEEP BOOP **
** scala.tools.nsc._ has been imported **
** New vals! Try repl, global, power **
** New cmds! :help to discover them **
** New defs! Type power.<tab> to reveal **
scala> settings.maxPrintString = 10000
scala> import global.definitions._
import global.definitions._
scala> (for{c1 <- ScalaValueClasses;
c2 <- ScalaValueClasses
isNSC = isNumericSubClass(c1, c2)
if isNSC
} yield ("isNumericSubClass (%s, %s) = %b" format (c1, c2, isNSC))).mkString("\n")
res5: String =
isNumericSubClass (class Byte, class Byte) = true
isNumericSubClass (class Byte, class Short) = true
isNumericSubClass (class Byte, class Int) = true
isNumericSubClass (class Byte, class Long) = true
isNumericSubClass (class Byte, class Float) = true
isNumericSubClass (class Byte, class Double) = true
isNumericSubClass (class Short, class Short) = true
isNumericSubClass (class Short, class Int) = true
isNumericSubClass (class Short, class Long) = true
isNumericSubClass (class Short, class Float) = true
isNumericSubClass (class Short, class Double) = true
isNumericSubClass (class Int, class Int) = true
isNumericSubClass (class Int, class Long) = true
isNumericSubClass (class Int, class Float) = true
isNumericSubClass (class Int, class Double) = true
isNumericSubClass (class Long, class Long) = true
isNumericSubClass (class Long, class Float) = true
isNumericSubClass (class Long, class Double) = true
isNumericSubClass (class Char, class Int) = true
isNumericSubClass (class Char, class Long) = true
isNumericSubClass (class Char, class Char) = true
isNumericSubClass (class Char, class Float) = true
isNumericSubClass (class Char, class Double) = true
isNumericSubClass (class Float, class Float) = true
isNumericSubClass (class Float, class Double) = true
isNumericSubClass (class Double, class Double) = true