Scala Enumeration: "override class"

0x7F800000

Top Contributor
Hallo allerseits

Ich kämpfe seit einigen Stunden daran, die Enumeration Klasse irgendwie zu "extenden". Es geht im wesentlichen um diese Bemerkung im Kommentar:
Code:
201	  /** A class implementing the <a href="Enumeration.Value.html"
202	   *  target="contentFrame">`Value`</a> type. This class can be
203	   *  overridden to change the enumeration's naming and integer identification
204	   *  behaviour.
205	   */
siehe den Quellcode hier: Scala Standard Library 2.9.1.final

Ich hab's ein wenig vereinfacht, und auf dieses etwas kürzere Beispiel heruntergebrüht:
Code:
// gaanz grobe skizze von Enumeration
class SimplifiedEnum{
  // alle instanzen werden mit hilfe einer factory-methode erzeugt
  // heisst im original 
  // protected final def Value(i: Int, name: String): Value = new Val(i, name)
  protected final def Value = new Val

  // abstrakte Value-Klasse
  abstract class Value{
    def bar(): Unit
  }
  
  // implementierung der Value classe, die irgendwie "ueberschrieben" werden soll
  protected class Val extends Value{
    def bar() = println("bar")
  }
}

// Erweiterung der Enumeration
class ExtendedEnum extends SimplifiedEnum{

  abstract class Value extends super.Value{
    // Versuch, eine neue funktionalitaet an Value dranzukleben
    def baz(): Unit
  }
  
  protected class Val extends Value{
    // implementierung der neuen funktionalitaet
	def baz() = println("new functionality, yuhu")
  }
}

object OverrideClassTest{

  // Anwendung der neuen ExtendedEnum klasse
  object MyExtEnum extends ExtendedEnum{
    val A = Value
	val B = Value
  }
  import MyExtEnum._
  
  
  def main(ignored: Array[String]){
    A.baz() // nix geht
  }
}
Der code funktioniert natürlich nicht, es soll nur demonstrieren, dass das erzeugen von neuen klassen mit gleichen namen nichts bringt: es werden stets die alten konstruktoren verwendet, und der typ der Values bleibt SimplifiedEnum#Value und nicht ExtendedEnum#Value.

Ich verstehe überhaupt nicht was der gute Herr Zenger hier gemeint hat: wie soll ich denn die Klasse "überschreiben"?

Irgendwelche wenig erleuchtende diskussionen darüber gab' schon bei Stack Overflow:
Overriding Scala Enumeration Value - Stack Overflow
Hier wird heldenhaft die Val Klasse überschrieben, das ändert aber immer noch nichts daran, dass zB. die [c]values()[/c]-Methode den alten typ [c]Set[SimplifiedEnumeration#Value][/c] zurückgibt.

enums - How does one "override" an inner class in Scala? - Stack Overflow
Hier wird die siskussion mit einem "Hm?" beendet, was mich auch nicht weiterbringt.

Kann das sein, dass man hier eigentlich einen virtuellen [c]type[/c] bräuchte, also den genauen type von Value erstmal variabel lassen sollte?
 
Zuletzt bearbeitet:

Landei

Top Contributor
Das Problem liegt im [c]protected final def Value = new Val[/c]: Wäre das nicht final, könnte man schreiben:

Code:
class SimplifiedEnum{
  // alle instanzen werden mit hilfe einer factory-methode erzeugt
  // heisst im original 
  // protected final def Value(i: Int, name: String): Value = new Val(i, name)
  protected  def Value = new Val //<---------------------------------- kein final

  // abstrakte Value-Klasse
  abstract class Value{
    def bar(): Unit
  }
  
  // implementierung der Value classe, die irgendwie "ueberschrieben" werden soll
  protected class Val extends Value{
    def bar() = println("bar")
  }
}

// Erweiterung der Enumeration
class ExtendedEnum extends SimplifiedEnum{

  protected class Val extends super.Val{
    // implementierung der neuen funktionalitaet
	def baz() = println("new functionality, yuhu")
  }
  
  override def Value = new Val //<------------------------------------ der Knackpunkt
}

object OverrideClassTest{

  // Anwendung der neuen ExtendedEnum klasse
  object MyExtEnum extends ExtendedEnum{
    val A = Value
	val B = Value
  }
  import MyExtEnum._
  
  
  def main(ignored: Array[String]){
    A.baz() // nix geht
  }
}

Du könntest höchstens eine implizite Umwandlung von [c]Val[/c] zu einer Klasse mit einem [c]baz()[/c] definieren. Enumerations finde ich relativ krank und unflexibel gelöst, und verwende lieber Fallklassen oder eigene Konstrukte.

Ich finde, Scala sollte Enumerations mit etwas Syntaxzucker zu Fallklassen übersetzen, dann würden sich viele Probleme von selber lösen
 
Zuletzt bearbeitet:

0x7F800000

Top Contributor
Das Problem liegt im [c]protected final def Value = new Val[/c]
Ja, das ist einfach ein weiteres symptom desselben problems: wenn man die methode überschreiben dürfte, würde es einfach eine zeile weiter hacken, dort wo man versucht, die Objekte vom neuen-Val Typ in die alte collection vom alten Typ zu quetschen. Man muss einfach nur den Typ variabel lassen.

Du könntest höchstens eine implizite Umwandlung von [c]Val[/c] zu einer Klasse mit einem [c]baz()[/c] definieren. Enumerations finde ich relativ krank und unflexibel gelöst, und verwende lieber Fallklassen oder eigene Konstrukte.
Das wäre keine gute Lösung, sondern ein temporärer Work-Around...

Ich finde, Scala sollte Enumerations mit etwas Syntaxzucker zu Fallklassen übersetzen, dann würden sich viele Probleme von selber lösen
Nein, der Fall ist zu unbedeutend, als dass man darauf syntaxzucker kippen sollte: scala verwendet syntaktischen zucker auf eine recht einheitliche und übersichtliche Art und weise (nämlich hauptsächlich simples Wegblenden von ätzenden Punkten, apply's, unapply's, getX, setX, unary_blup etc: also hauptsächlich dort, wo man sich auf mathematische konventionen für Operatoren verlassen kann). Extra für Enumerations zusätzliche Regeln zu erfinden wäre imho nicht schön: da stimmt die Balance zwischen komplexität und nützlichkeit nicht mehr. Die Implementierung von Enumeration ist in den Ansätzen ja völlig okay, nur hat man da an eine Stelle dieses zu paranoide final reingepackt. Was meinst du, kriegt man das noch abgeändert? ???:L
 

Landei

Top Contributor
Ich sehe keine Möglichkeit außer dem implicit-Hack. Vielleicht solltest du das Problem mal auf die Scala-User-Mailinglist loslassen.
 

0x7F800000

Top Contributor
Ich sehe keine Möglichkeit außer dem implicit-Hack. Vielleicht solltest du das Problem mal auf die Scala-User-Mailinglist loslassen.
Ich komme mit Mailing-Listen ehrlich gesagt nicht klar: letztes Mal, als ich versucht habe da durchzublicken, habe ich es nicht hinbekommen auf ältere Beiträge zu reagieren, die vor dem subscriben schon da waren, ich raff' nicht, wie man einen haufen e-mails "pullen" kann. Ebensowenig verstehe ich, warum mir irgendein kram "gepusht" wird, für den ich mich überhaupt nicht interessiere... Wie ich eine Mail editiere: keine Ahnung, sorry, ich versteh's nicht, ich dachte eine Mail ist weg, wenn man die abgeschickt hat? Wo da die Code-Tags sein sollen: ebenfalls bahnhof ???:L . Mails scheinen mir irgendwie komplett das antagonistische Medium zu einem Board zu sein, deswegen kann ich nicht wirklich nachvollziehen, warum man so etwas merkwürdiges verwendet.

Vor allem verstehe ich nicht, warum die Leute seit so vielen jahren es nicht hinkriegen können (bzw. nicht wollen), ein lesbares übersichtliches, für jeden Idioten (wie mich) zugängliches board aufzusetzen, mit 3 Knöpfen: anmelden, absenden, bearbeiten... :autsch:

Was mein konkretes Problem angeht, so habe ich es mit einer komplett neuen Klasse gelöst, die in gewissen Implementierungsdetails(der Reflection-Teil) an Enumeration angelehnt ist: bei der genaueren Betrachtung habe ich festgestellt, dass das, was ich haben wollte, nur sehr oberflächlich mit Enumeration zu tun hatte, und deswegen habe ich die Idee aufgegeben, von Enumeration abzuleiten. Enumeration tut was es soll, dass es sich nicht in das umbiegen lässt, was ich mir da ausgedacht habe, ist daher nicht das problem von Enumeration, sondern mein, und das habe ich gelöst.

Danke für die anderen Lösungsvorschläge :)
 

Ähnliche Java Themen

Neue Themen


Oben