22. Mehrfachbeerbung Inhaltsverzeichnis 24. Einschränkung des Typparameters

23. XML

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]

22. Mehrfachbeerbung Inhaltsverzeichnis 24. Einschränkung des Typparameters

[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