2013-10-29 4 views
5

Sto invocando in modo riflessivo un metodo il cui argomento potrebbe o potrebbe non essere un'istanza di value class. Poiché lo scopo delle classi di valore è di evitare il pugilato del valore sottostante, se il tipo di parametro è value class allora il metodo in questione si aspetterà in effetti un valore unboxed. Per gestire questo caso sto cercando di scartare il valore sottostante dalla value class. Ho bisogno di determinare se l'argomento è di una classe di valore, e qui mi ha colpito il primo ostacolo:Scala: riconoscimento degli oggetti delle classi di valore

def isObjectOfValueClass(arg: Any) = 
    classOf[AnyVal].isAssignableFrom(arg.getClass) 

Questo non funziona come previsto, come il metodo restituisce true per:

case class NonValueClass(underlying: Int) 

Come può essere implementato isObjectOfValueClass? O c'è un modo più semplice per richiamare in modo riflessivo un metodo che potrebbe prendere come oggetto un oggetto di valore?

+1

A proposito, la classe di valori può includere non solo le primitive ma anche gli oggetti. –

risposta

3

Innanzitutto, si noti che il proprio isObjectOfValueClass riceverà una versione in box delle istanze della classe di valore.

In secondo luogo, non può funzionare come si desidera. È perché classOf[AnyVal] == classOf[AnyRef] == <java.lang.Object>.

Non c'è modo di runtime di distinguere tra una classe di valore in scatola e una classe di riferimento (Any non hanno .instanceOf[T], AnyVal non possono essere utilizzati in pattern matching o come parametro di .instanceOf[T], e ciò che è più importante, classi di valore compilate non lo fanno estendere o implementare AnyVal).

Se lo vuoi deciso fase di compilazione, quindi provare:

case class IsAnyVal[-T](val value: Boolean) extends AnyVal 
implicit def _noClueHowToNameThisImplicit_1 = IsAnyVal[AnyVal](true) 
implicit def _noClueHowToNameThisImplicit_2 = IsAnyVal[AnyRef](false) 
def isAnyVal[T](arg: T)(implicit ev: IsAnyVal[T]) = ev.value 

scala> isAnyVal(1) 
res4: Boolean = true 

scala> isAnyVal("") 
res5: Boolean = false 

io non sono sicuro di come si desidera estrarre il solo campo delle istanze di classe valore boxed rilevati senza la boxe più accidentale. Inoltre, Hotspot è abbastanza bravo nell'ottimizzare piccoli oggetti di breve durata.