2013-08-27 14 views
11

Sto cercando di comprendere meglio l'utilizzo corretto dei metodi apply e unapply.Comprendere come utilizzare apply e unpply

Considerando un oggetto che vogliamo serializzare e deserializzare, questo è un uso corretto (vale a dire il modo in cui Scala ) di utilizzare apply e unapply?

risposta

3

Quindi applicare e unapply sono solo defs con supporto di sintassi aggiuntivo.

Applica accetta argomenti e per convenzione restituirà un valore correlato al nome dell'oggetto. Se consideriamo le case class di Scala come un uso "corretto", l'oggetto Foo's apply costruirà un'istanza di Foo senza bisogno di aggiungere "nuovo". Ovviamente sei libero di fare applicare qualsiasi cosa desideri (la chiave per valutare in Map, set contiene valore in Set e l'indicizzazione in Seq ti viene in mente).

Unapply, se restituire un'opzione o Booleano può essere utilizzato in corrispondenza di corrispondenza {} e modello. Come si applica è solo una def in modo da poter fare tutto ciò che si sogna, ma l'uso comune è quello di estrarre valore (s) da istanze della classe compagno dell'oggetto.

Dalle librerie con cui ho lavorato con la serializzazione/deserializzazione, i difetti tendono ad essere nominati esplicitamente. Ad esempio, scrittura/lettura, spettacolo/lettura, Tox/fromX, ecc

Se si desidera utilizzare richiedere/unapply a questo fine l'unica cosa che suggerirei sta cambiando a

def unapply(f: Foo): Option[JValue] 

Poi si potrebbe fare qualcosa di simile:

val myFoo = Foo("""{name: "Whiskers", age: 7}""".asJson) 
// use myFoo 

val Foo(jval) = myFoo 
// use jval 
28

In primo luogo, apply e unapply non sono necessariamente opposti l'uno dall'altro. Infatti, se ne definisci uno su una classe/oggetto, non devi definire l'altro.

applicano

apply è probabilmente il più facile da spiegare. Essenzialmente, quando tratti il ​​tuo oggetto come una funzione, applica è il metodo che viene chiamato, quindi Scala gira:

obj(a, b, c) a obj.apply(a, b, c).

unapply

unapply è un po 'più complicato. È utilizzato nel meccanismo di corrispondenza dei modelli di Scala e il suo uso più comune che ho visto è in Extractor Objects.

Per esempio, ecco un oggetto giocattolo estrattore:

object Foo { 
    def unapply(x : Int) : Option[String] = 
    if(x == 0) Some("Hello, World") else None 
} 

Così ora, se si utilizza questo è in un match modello in questo modo:

myInt match { 
    case Foo(str) => println(str) 
} 

Supponiamo myInt = 0. Allora cosa succede? In questo caso viene chiamato il numero Foo.unapply(0) e, come puoi vedere, restituirà Some("Hello, World"). Il contenuto di Option verrà assegnato a str quindi, alla fine, la corrispondenza del modello sopra verrà stampata "Ciao, mondo".

Ma cosa succede se myInt = 1? Quindi Foo.unapply(1) restituisce None in modo che l'espressione corrispondente per tale modello non venga chiamata.

Nel caso di incarichi, come val Foo(str) = x questo è zucchero sintattico per:

val str : String = Foo.unapply(x) match { 
    case Some(s) => s 
    case None => throw new scala.MatchError(x) 
} 
+0

un po 'strano che hai chiamato l'int 'str' ma a parte questo, molto bello spiegazione;) – Nicofisi

+0

il punto è che 'str' è in realtà un' String' non un 'Int', perché questo è un tipo molto particolare di oggetto estrattore :) – amnn