2015-02-20 21 views
8

Sto cercando di ottenere un esempio di upickle di base per funzionare e sembra che manchi qualcosa qui. Voglio provare l'esempio fornito in the readme page for upickleuPickle e ScalaJS: serializzazione dei tratti sigillati

import upickle._ 

sealed trait A 
@key("Bee") case class B(i: Int) extends A 
case object C extends A 

Poi, il mio codice è:

object Model { 
    def main(args: Array[String]): Unit = { 

    val a = B(5): A 
    println(a) 

    val out = write(a) 
    println(out) 

    val a2 = read[A](out) 
    println(a2) 

    println(a == a2) 

    } 
} 

Tutto quello che ottiene è l'errore:

The referenced trait [[A]] does not have any sub-classes. This may happen due to a limitation of scalac (SI-7046) given that the trait is not in the same package. If this is the case, the hierarchy may be defined using integer constants.

ho due domande:

  • Come posso convincere uPickle tha il tratto è nello stesso pacchetto? (Perché lo è.)
  • O se non posso: come posso definire la gerarchia con le costanti integer?

risposta

8

Hai mai avuto la sindrome che puoi dedicare più ore a un problema come questo e lo risolvi minuti dopo aver fatto la domanda StackOverflow?

Si scopre che a causa di compiler-specific details, tale tratto sigillato non conoscerà le sue sottoclassi dirette fino a dopo il punto nel file in cui è definito. Quindi, in questo caso, avevo definito il tratto e i suoi casi dopo il il metodo principale, in cui il upickle avrebbe fatto la sua espansione macro e la magia. A questo punto, non conoscerà i casi del tratto. Se il metodo principale viene spostato nello stesso file dopo la definizione del tratto e dei suoi casi, funzionerà.

+1

Il mio codice funzionava bene fino a quando ho rinominato il pacchetto in cui si trovavano le mie trait/sottoclassi. Per qualche motivo, devono essere stati compilati in un ordine diverso. Mi stavo seriamente grattando la testa. Grazie per questo. –

2

Ho riscontrato questo errore in un progetto Scala.js in cui ho condiviso una classe astratta sigillata tra server e client.

La soluzione era utilizzare lo Typelevel compiler invece del predefinito Lightbend.

Questo è fatto facilmente:

  1. mettere questo nel vostro build.properties: sbt.version=0.13.13-M1
  2. e questo nella parte superiore del vostro build.sbt: scalaOrganization in ThisBuild:= "org.typelevel"

Per completezza, questo è la classe che ora posso condividere tra client e server:

sealed abstract class ServerResponse 

case class Ok(msg: String) extends ServerResponse 

case class Failure(msg: String) extends ServerResponse