2015-02-20 5 views
8

Próbuję uzyskać podstawowy przykład do pracy i wydaje mi się, że czegoś tutaj brakuje. Chcę wypróbować przykład podany w the readme page for upickleuPickle i ScalaJS: serializacja serii zabezpieczonej

import upickle._ 

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

Następnie, mój kod jest:

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) 

    } 
} 

All I get to błąd:

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.

Mam dwa pytania:

  • Jak mogę przekonać się, z jakiego t cecha jest w tym samym pakiecie? (Ponieważ jest.)
  • Lub jeśli nie mogę: jak zdefiniować hierarchię ze stałymi całkowitymi?

Odpowiedz

8

Czy kiedykolwiek miałeś syndrom, że możesz spędzić wiele godzin na takim problemie, i rozwiązujesz go kilka minut po zadaniu pytania StackOverflow?

Okazuje się, że z powodu compiler-specific details, taka zapieczętowana cecha nie będzie znać swoich bezpośrednich podklas, aż do momentu w pliku, w którym została zdefiniowana. Tak więc w tym przypadku zdefiniowałem tę cechę i jej przypadki jako główną metodę, w której upickle wykonywałoby ekspansję makr i magię. W tym momencie nie będzie wiedział o przypadkach cechy. Jeśli główna metoda zostanie przeniesiona do tego samego pliku po zdefiniowaniu cechy i jej przypadków, zadziała.

+1

Mój kod działał poprawnie, dopóki nie zmieniłem nazwy pakietu, w którym znajdowała się moja cecha/podklasy. Z jakiegoś powodu musiały zostać skompilowane w innej kolejności. Poważnie podrapałem się po głowie. Dzięki za to. –

2

Napotkano ten błąd w projekcie Scala.js, w którym udostępniłem zamkniętą klasę abstrakcji między serwerem a klientem.

Rozwiązaniem było użycie Typelevel compiler zamiast domyślnego Lightbend.

to łatwo zrobić:

  1. umieścić to w swoim build.properties: sbt.version=0.13.13-M1
  2. i to na górze build.sbt: scalaOrganization in ThisBuild:= "org.typelevel"

kompletności boską, to to klasa, którą mogę teraz udostępniać między klientem a serwerem:

sealed abstract class ServerResponse 

case class Ok(msg: String) extends ServerResponse 

case class Failure(msg: String) extends ServerResponse