2017-03-24 9 views
2

Ich habe ein Problem mit einigen Scala-Code und versuche, eine schlechte Klasse Design auszuschließen (na ja, Konstruktor Design), bevor ich beginne, es als ein Netzwerk-Problem zu behandeln.Scala Konstruktoren mit Val nicht gut mit Serialisierung Framework

So habe ich ein Modell Scala Klasse Hail genannt:

class Hail(val handle : String, val message : String) extends BaseMessage { 
    def this() { 
    this("default_user", "default_message") 
    } 
} 

abstract class BaseMessage extends AbstractMessage(true) { 
} 

// This is a 3rd party open source class written in Java 
public abstract class AbstractMessage implements Message 
{ 
    private transient boolean reliable = true; 

    protected AbstractMessage() 
    { 
    } 

    protected AbstractMessage(boolean reliable) 
    { 
     this.reliable = reliable; 
    } 

    public Message setReliable(boolean f) 
    { 
     this.reliable = f; 
     return this; 
    } 

    public boolean isReliable() 
    { 
     return reliable; 
    } 
} 

// This is also a 3rd party open source class written in Java 
public interface Message 
{ 
    public Message setReliable(boolean f); 

    public boolean isReliable(); 
} 

Zur Laufzeit Instanzen dieser Klasse serialisiert erhalten (binär), über den Draht an einen Server gesendet, wo sie deserialisiert werden (wieder in Hail Instanzen) und verarbeitet.

So habe ich Client-Code, der wie folgt aussieht:

val h1 : Hail = new Hail("user1", "Hello!") 
val h2 : Hail = new Hail("user2", "Aloha!") 
val h3 : Hail = new Hail("user3", "Bien venu mes amigos") 

client.send(h1) 
client.send(h2) 
client.send(h3) 

Wenn der Server diese Nachrichten empfängt, druckt er ihren Griff/Nachricht Combos STDOUT aus. Die Nachrichten, die ich erhalten sind wie folgt:

Server received a Hail: default_user, default_message 
Server received a Hail: default_user, default_message 
Server received a Hail: default_user, default_message 

Statt dessen, was ich erwartet werden:

Server received a Hail: user1, Hello! 
Server received a Hail: user1, Aloha! 
Server received a Hail: user3, Bien venu mes amigos 

Wieder, diese konnte eine Vernetzung/Serialisierung/serverseitige Problem werden . Aber bevor ich auf diese Route gehe, möchte ich sicherstellen, dass meine Klasse Hail korrekt geschrieben wurde.

Das Serialisierungsframework, das ich benutze erfordert alle Nachrichten (wie Hail) haben keine arg Konstruktoren (daher die eine, die ich oben zur Verfügung gestellt). So scheint es mir, dass etwas mit meinem anderen Konstruktor falsch ist, und vielleicht ruft der Server standardmäßig den No-Arg-Konstruktor auf, weil er sonst nichts verwenden kann.

ich dekompilierten meine Hail Klasse und die folgende sehen:

@ScalaSignature(bytes="<lots of bytes here omitted for brevity") 
public class Hail 
    extends BaseMessage 
{ 
    private final String handle; 

    public String handle() 
    { 
    return this.handle; 
    } 

    public String message() 
    { 
    return this.message; 
    } 

    public Hail() 
    { 
    this("default_user", "default_message"); 
    } 

    public Hail(String handle, String message) {} 
} 

Gleich mehrere Dinge sind neugierig/argwöhnisch zu mir: (!, Die gewünscht wird)

  • Obwohl ich private final String handle sehen, Ich sehe kein reziprokes private final String message Feld ...
  • Auch der 2. Konstruktor (public Hail(String handle, String message)) ist leer/undefiniert. Dies ist wahrscheinlich die Wurzel meiner Probleme.

Also frage ich, wie kann ich Hail ‚s Quelle Refactoring, so dass das folgende Endergebnis Bytecode ist, dass würde decompile zu:

@ScalaSignature(bytes="<lots of bytes here omitted for brevity") 
public class Hail 
    extends BaseMessage 
{ 
    private final String handle; 

    public String handle() 
    { 
    return this.handle; 
    } 

    public String message() 
    { 
    return this.message; 
    } 

    public Hail() 
    { 
    this("default_user", "default_message"); 
    } 

    public Hail(String handle, String message) 
    { 
    this.handle = handle; 
    this.message = message; 
    } 
} 

Irgendwelche Ideen?

+1

Bitte auch 'BaseMessage' anzeigen. Enthält es das Feld "Nachricht"? – Thilo

+1

Danke @Thilo (+1) - Ich habe die Frage aktualisiert und die vollständige Klassenhierarchie bereitgestellt. Die "AbstractMessage" -Klasse und die "Message" -Schnittstelle stammen aus einer Bibliothek von Drittanbietern. – smeeb

+0

Diese Dekompilierung muss irgendwie unvollständig sein. Wenn es sich auf "this.message" bezieht, sollte das irgendwo definiert werden. – Thilo

Antwort

3

Das Problem besteht darin, dass serial-serialisierer den Konstruktor no-arg verwendet und dann die Werte der veränderbaren Parameter in der Klasse ändern.

Scala val s sind jedoch nicht änderbar, daher werden sie als final Parameter Ihrer Klasse kompiliert und können daher nicht mutiert werden.Daher werden die Objekte mit den Standardwerten instanziiert und behalten dann diese Werte bei, da sie nicht mutiert werden können.

Ich würde empfehlen, einen Scala-kompatiblen Serialisierer zu verwenden, aber eine einfachere Lösung besteht darin, die Eigenschaften mutieren zu lassen, indem man sie als var s anstelle von val s deklariert.

Verwandte Themen