2.8 :clean()

Diese Methode kann an Objekten eines Dialogs oder Moduls vor deren endgültiger Zerstörung noch Aktionen zum Säubern der Objekte (freigeben von zuvor allokierten Ressourcen) vornehmen. Die Methode ist an allen Objekten, Modellen und Defaults vordefiniert, kann jedoch überschrieben werden, um benutzerdefinierte Aktionen an den Objekten vorzunehmen.

Die :clean()-Methode kann nicht explizit aufgerufen werden. Die Aufrufe erfolgen ausschließlich implizit:

  1. Wenn ein Dialog oder Modul entladen werden soll, wird die :clean()-Methode für alle Objekte, Modelle und Defaults des Dialogs bzw. Moduls nach der finish-Regel aufgerufen.
  2. Wenn ein Objekt oder Modell zur Laufzeit zerstört wird (Aufruf der :destroy()-Methode, eingebauten Funktion destroy() oder Schnittstellenfunktion DM_Destroy() bzw. DMcob_Destroy()), wird die :clean()-Methode unmittelbar vor der Zerstörung für dieses Objekt aufgerufen.

Definition

void :clean
(
)

Parameter

Keine.

Redefinition

Zur Redefinition der Methode genügt es, einfach an einem Objekt folgendes zu schreiben:

window W {
  :clean()
  {
    ...
    // Code um etwas freizugeben oder Daten in konsistenten Zustand zu bringen.
    ...
  }
}

Möchte man einen Teil der Aufgaben an die Superklasse delegieren, so kann mit this:super() die :clean()-Methode des in der Vererbungshierarchie weiter oben liegenden Modells oder Defaults aufgerufen werden.

Hinweis

Der Aufruf von this:super() hat bei der :clean()-Methode eine weitere wichtige Funktion. Erfolgt der Aufruf dieser Methode auf der obersten Ebene (typischerweise dem Default), auch wenn es dort formal keine Superklasse mehr gibt, so werden die :clean()-Methoden an den Kindern des Objektes ebenfalls ausgeführt. Demzufolge können die Aufrufe der :clean()-Methoden für die Kinder unterdrückt werden, wenn irgendwo in der Vererbungshierarchie kein Aufruf von this:super() erfolgt.

Beispiel

dialog CLEAN

default record {
  :clean() {
    print "== DEFAULT >>>";
    this:super();
    print "== DEFAULT <<<";
  }
}

model record MRec1 {
  :clean() {
    print "== MRec1 >>>";
    this:super();
    print "== MRec1 <<<";
  }

  child record R1 {
    :clean() {
      print "== R1 >>>";
      this:super();
      print "== R1 <<<";
    }
  }
  child record R2 {
    :clean() {
      print "== R2 >>>";
      this:super();
      print "== R2 <<<";
    }
  }
}

model MRec1 MRec2 {
  :clean() {
    print "== MRec2 >>>";
    // Kein Aufruf von this:super().
    print "== MRec2 <<<";
  }
}

model MRec1 MRec3 {
  // Hier tritt die vordefinierte :clean()-Methode in Aktion.
  child record R3 {
    :clean() {
      print "== R3 >>>";
      this:super();
      print "== R3 <<<";
    }
  }
}

on dialog start
{
  variable object O;

  O := MRec2:create(CLEAN);
  print "on start: Destroy";
  O:destroy();
  // Kein :clean() der Kinder R1 und R2.

  O := MRec3:create(CLEAN);
  print "on start: Destroy";
  O:destroy();
  // :clean()-Methoden der Kinder R1, R2 und R3 werden aufgerufen.

  exit();
}

Der abgeänderter Ausschnitt aus der Trace-Datei soll verdeutlichen, was bei der Ausführung dieses Codes passiert.

"on start: Destroy"
    "== MRec2 >>>"
    "== MRec2 <<<"
// Kein :clean() der Kinder R1 und R2.

"on start: Destroy"
    "== MRec1 >>>"
        "== DEFAULT >>>"
      "== R1 >>>"
          "== DEFAULT >>>"
          "== DEFAULT <<<"
      "== R1 <<<"
      "== R2 >>>"
          "== DEFAULT >>>"
          "== DEFAULT <<<"
      "== R2 <<<"
      "== R3 >>>"
          "== DEFAULT >>>"
          "== DEFAULT <<<"
      "== R3 <<<"
        "== DEFAULT <<<"
    "== MRec1 <<<"
// :clean()-Methoden der Kinder R1, R2 und R3 werden aufgerufen.