Um eine möglichst allgemeine abstrakte Oberklasse für die persistenten Implementierungen zu entwickeln, verwenden wir XML und Reflexion. Diese ermöglichen, Typinformation als XML-Attribut für jedes Element zu speichern; die Wiederherstellung der Objekte erfordert aber einen String-parametrisierten Konstruktor des aktuellen Typparameters (E). Die Implementierung funktioniert auch für eine Warteschlange mit Elementen unterschiedlicher Typen, (s.Abbildung 22).
/** Persistence for Iterable with XML file - PersItQ.scala
* @param E must have String parameterized constructor */
import scala.xml._
trait PersItQ[E] extends PersQ[E] with collection.Iterable[E] {
def save(filename: String) = {
var wurzel = <queue/> // [1]
val i = this.iterator
while (i.hasNext) {
val e = i.next
/* Um die Typinformation der Elemente nicht zu verlieren,werden die Attribute "type" mitgeschrieben: */
val attribut = new UnprefixedAttribute("type", e.asInstanceOf[AnyRef].getClass.getName, Null) // [2]
val element = Elem(null, "element", attribut, TopScope, Text(e.toString)) // E wird nach String konvertiert
wurzel = wurzel match {
case <queue>{inhalt@_*}</queue> => // [3]
<queue>{inhalt}{element}</queue> } }
XML.save(filename, wurzel); } // [4]
def load(filename: String) = {
this.clear
val wurzel = XML.loadFile(filename)
for (element <- wurzel \\ "element") { // [5]
val wert = element.text
val typ = (element \ "@type").text // [6]
this.add(Class.forName(typ).asInstanceOf[Class[E]]. // [7]
getConstructor(Class.forName("java.lang.String")). // [8]
newInstance(wert)) } } } // [9]
Dieses Trait kann nun ohne weitere Programmierung in die Queue-Implementierungen eingemischt werden:
class PersItArrayQ[E](size: Int) extends ArrayQ[E](size) // [10]
with ItArrayQ[E] with PersItQ[E]
class PersItListQ[E] extends ItListQ[E] with PersItQ[E]
[1] Dieses XML-Literal stellt ein scala.xml.Elem-Objekt dar.
[2] Ohne Konvertierung zu AnyRef stoßt der Inferenzmechanismus auf Zweideutigkeiten.
[3] Diese Mustererkennung ersetzt den alten Inhalt von <queue> mit dem angefügten element
[4] So einfach ist es in Scala aus einem XML-Element ein XML-Dokument zu machen.
[5] \\ ist ein Operator aus der Klasse scala.xml.Elem; entspricht etwa getElementsByTagName
[6] der Attribut "type" wird gelesen
[7] Reflexion ist nötig, um aus dem String in XML ein E-Objekt wiederherzustellen
[8] getConstructor ist eine Methode aus java.lang.Class, liefert ein Object vom Typ java. lang.reflect.Constructor, das den Konstruktor (hier mit einem String-Parameter) darstellt
[9] newInstance ist eine Methode aus java.lang.reflect.Constructor; führt den Konstruktor aus
[10] ArrayQueue muss erwähnt werden, um ihm die Klassenparameter zu übergeben
Version: 5. Dezember 2010
© Prof. Solymosi, 2010, Beuth-Hochschule für Technik Berlin