Jak wiemy, możemy dodawać (odejmować/mnożyć/itp.) Dwie liczby różnych typów Numeric
, a wynikiem będzie szerszy z dwóch typów, niezależnie od ich kolejności.Parametry typu i poszerzenie numeryczne
33F + 9L // Float + Long == Float
33L + 9F // Long + Float == Float
Jest tak, ponieważ każda z 7 Numeric
klas (Byte
, Short
, Char
, Int
, Long
, Float
, Double
) ma 7 różnych +()
metody (i -()
, *()
itp), po jednym dla każdego Numeric
Typ które można odebrać jako przekazany parametr. [Nie ma dodatkowy +()
metoda obsługi parametru String
, ale to nie musi dotyczyć nas tutaj.]
teraz rozważyć następujące kwestie:
implicit class PlusOrMinus[T: Numeric](a: T) {
import Numeric.Implicits._
def +-(b: T) = if (util.Random.nextBoolean) a+b else a-b
}
To działa, jeśli dwa operandy są tego samego typu, ale działa również, gdy typ pierwszego operandu jest szerszy niż typ drugiego.
11F +- 2L // result: Float = 9.0 or 13.0
wierzę, co się tutaj dzieje jest to, że kompilator używa weak conformance osiągnąć numeric widening na 2. argumentu (parametr b
), jak to jest przekazywane do metody +-()
.
Ale pierwszy operand nie zostanie poszerzony, aby pasował do drugiego. Nawet się nie skompiluje.
11L +- 2F // Error: type mismatch; found: Float(2.0) required: Long
Czy jest jakiś sposób obejścia tego ograniczenia?
Nie mogę użyć innego parametru typu dla argumentu b
(def +-[U: Numeric](b: U) = ...
), ponieważ Numeric
, wyrażony za pomocą parametru typu, może tylko dodawać/odejmować własny typ.
jest jedynym rozwiązaniem, aby stworzyć 7 różnych klas (PlusOrMinusShort/Int/Long/
etc.) z 7 różnymi metodami (def +-(b:Short)
, def +-(b:Int)
, def +-(b:Long)
, itd.)?