2016-07-31 10 views
1

Ich habe in meinem Projekt Objekte, die IDs darstellen.Scala Wert Klasse mehrere Vererbung

Sagen wir es ist ChairId, TableId, LampId. Ich möchte, dass sie alle von GenericId erben. Und ich möchte anrufen def f(x: GenericId) = x.id

Ich möchte, dass sie nur einzelne id: String halten, damit ich möchte, dass sie AnyVal erweitern.

Auch würde ich für jeden Typ wie Funktion bereitzustellen generate die meine spezifische ID dh erzeugen würde ich möchte etwas geben wie ChairId.generate()

ich diese eingegeben haben:

sealed abstract class GenericId(val id: String) 
final case class ChairId(override val id: String) extends GenericId(id) 
final case class TableId(override val id: String) extends GenericId(id 

Und ich aber, wenn GenericId würde von AnyVal erben, was funktionieren würde, aber bisher kein Glück;/Ich habe auch versucht, GenericId zu einem Merkmal zu machen und Case-Klassen AnyVal mit GenericId zu erweitern, aber auch nicht compilieren:/

Anot ihre Sache mit TableId.generate() Ich kann Companion Objekt nur mit der Funktion generate und das im Grunde mein Problem zu lösen, aber ich fragte mich, ob es die Möglichkeit gibt, das zu lösen, ohne Begleiter-Objekt zu definieren? (Dh durch implicits irgendwie)

// bearbeiten

Kommentar über Code zur Verfügung zu stellen, die nicht kompilieren lässt (und ich möchte):

sealed abstract class AbstractId(val id: String) extends AnyVal 
final case class CatId(override val id: String) extends AbstractId(id) 
final case class DogId(override val id: String) extends AbstractId(id) 
+0

Ich bin mir nicht ganz sicher, was Sie hier fragen. Wenn mehrere Fragen vorhanden sind, möchten Sie sie möglicherweise in mehrere Stack Overflow-Fragen aufteilen. –

+0

Bitte fügen Sie den Code und die Kompilierungsfehler für die Dinge, die Sie ausprobiert haben, ein. Ich denke, das wäre hilfreich. –

Antwort

3

Wertklassen nicht auf diese Weise für eine Arbeit kann einige Gründe.

Erstens, von der documentation, können Wertklassen nicht durch eine andere Klasse erweitert werden, so AbstractId kann AnyVal nicht erweitern. (Limitation #7)

scala> abstract class AbstractId(val id: String) extends AnyVal 
<console>:10: error: `abstract' modifier cannot be used with value classes 
     abstract class AbstractId(val id: String) extends AnyVal 
        ^

Zweitens auch wenn Sie AbstractId machen einen Zug, und definieren Sie die anderen IDs wie folgt aus:

final case class DogId(val id: String) extends AnyVal with AbstractId 

.. die Nutzung der Wertklasse würde nicht passen Ihre Fall, weil die Klasse selbst immer noch zugeordnet würde. Siehe allocation summary:

wird ein Wert Klasse tatsächlich instanziiert, wenn:

  1. ein Wert Klasse als eine andere Art behandelt wird.
  2. Eine Wertklasse wird einem Array zugewiesen.
  3. Ausführen von Laufzeittests, z. B. Mustererkennung.
+0

Du schlägst mich für ein paar Sekunden :) – pedrofurla

1

Einige Zitate aus dem value classes SIP, die Ihre Zweifel wahrscheinlich sind zu klären: Klassen

Wert ...

  1. ... muss eine öffentliche, val mit genau Parameter nur einen primären Konstruktor haben, deren Typ nicht ein Wert Klasse.

  2. ... kann nicht durch eine andere Klasse erweitert werden.

Per 1. kann es nicht abstrakt sein; pro 2. Ihre Codierung funktioniert nicht.

Es gibt einen weiteren Nachteil:

Ein Wert Klasse kann nur universelle Züge erweitern und kann nicht verlängert werden kann selbst. Ein universelles Merkmal ist ein Merkmal, das Any erweitert, nur als Mitglieder hat und keine Initialisierung durchführt. Universelle Merkmale ermöglichen die grundlegende Vererbung von Methoden für Wertklassen , aber sie verursachen den Overhead der Zuordnung.

Mit allem daran, basierend auf dem letzten Schnipsel, dies funktionieren könnte:

sealed trait AbstractId extends Any { def id: String } 
final case class CatId(id: String) extends AnyVal with AbstractId 
final case class DogId(id: String) extends AnyVal with AbstractId 

Aber bedenken Sie nur die Zuordnung tritt auf, wenn Sie CatId und DogId als AbstractId verwenden möchten. Zum besseren Verständnis empfehle ich das Lesen des SIP.