2.40 :set()

Diese Methode kann Attribute an einem Objekt setzen. Sie ist an allen Objekten, Modellen und Defaults vordefiniert.

Darüber hinaus ist es möglich, diese Methode zu überschreiben und somit die Art und Weise wie Attribute gesetzt werden um weitere Aktionen (z.B. Konsistenzprüfungen) zu erweitern.

Die dabei zulässigen Attribute für den jeweiligen Objekttyp entnehmen Sie bitte der „Objektreferenz“.

Definition

boolean :set
(
      attribute Attribute input,
      anyvalue  Value     input
  { , anyvalue  Index     input }
  { , boolean   SendEvent := true input }
)

Parameter

attribute Attribute input
In diesem Parameter wird der Methode mitgeteilt, welches Attribut gesetzt werden soll.
anyvalue Value input
In diesem Parameter wird der gewünschte, neue Wert übergeben, den das Attribut annehmen soll.
anyvalue Index input
Dieser optionale Parameter muss übergeben werden, wenn ein indiziertes Attribut gesetzt werden soll. Sein Datentyp muss dem Index-Datentyp des Attributs entsprechen. Soll also ein eindimensionales Attribut gesetzt werden, so wird hier ein integer-Wert erwartet. Wenn es sich hingegen um ein zweidimensionales Attribut handelt, so muss hier ein index-Wert übergeben werden.
boolean SendEvent := true input
Über diesen optionalen Parameter wird gesteuert, ob durch das erfolgreiche Setzen des Attributes ein changed-Ereignis verschickt werden soll oder nicht. Wenn kein Ereignis verschickt werden soll, muss hier false übergeben werden. Der Standardwert ist true, sodass ein Ereignis verschickt wird, auch wenn hier nichts angegeben wird.

Rückgabewert

true
Die Methode liefert true zurück, wenn das Setzen des Attributs erfolgreich war.
false
Wenn das Setzen des Attributs abgelehnt wurde (entweder vom IDM oder IDM-Programmierer), wird false zurückgeliefert.

Impliziter Aufruf

Die Methode :set() wird auch implizit aufgerufen. Bei Veränderung eines Attributs (vordefiniert oder benutzerdefiniert) aus der Regelsprache (durch Zuweisung mit := bzw. ::= oder die eingebaute Funktion setvalue()) oder mit einer Schnittstellenfunktion (z.B. DM_SetValue()), wird die Methode :set() aufgerufen, die dann das eigentliche Setzen des Attributs durchführt. Der Aufruf der Methode :set() erfolgt dabei in der Mitte und führt die eigentliche Zuweisung des neuen Werts durch.

Redefinition

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

window W {
  :set(<keine Parameter!>)
  {
    ...
    Aktionen, um ein Attribut zu setzen.
    ...
  }
}

Innerhalb der Methodendefinition können die Parameter Attribute, Value, Index und SendEvent abgefragt und gesetzt werden, um dann z.B. mit this:super() die Methode :set() der Superklasse mit den entsprechend veränderten Parametern aufzurufen. Die Änderung der Parameter wie Attribute und Index ist allerdings nicht sinnvoll, da solcher Code schwer zu verstehen wäre.

Unterdrückung von rekursiven Aufrufen

Wird in der Methode :set() irgendein Attribut des selben Objektes, für das die Methode :set() bereits aufgerufen worden ist, gesetzt, so müsste eigentlich wieder die Methode :set() für das selbe Objekt implizit aufgerufen werden. Da dabei die Gefahr von Endlosrekursionen sehr groß ist, wird ein solcher rekursiver Aufruf unterdrückt.

Beispiel

window {
  :set()
  {
    case (Attribute)
    in .title:
      this.title := "<" + Value + ">";
        // Kein impliziter Aufruf von :set().
        // Wegen ":=" wird ein "changed"–Ereignis verschickt.
        // Mit "::=" könnte der IDM-Programmierer auch dies unterdrücken.
      OtherObject.title := "<" + Value + ">";
        // :set() von OtherObject wird aufgerufen.
        // Der SendEvent-Parameter von :set() wird auf "true" gesetzt.
    otherwise:
      this:super();
    endcase
  }
}

In diesem Beispiel wird innerhalb der Methode :set() das Setzen des Fenstertitel überwacht und der Titel in <> eingeklammert. Während der Zuweisung this.title := … wird die Methode :set() nicht nochmals aufgerufen. Die Methode :set() für ein anderes Objekt wird sehr wohl aufgerufen.

Aufruf der Methode :set() an der übergeordneten Klasse

Das obige Beispiel zeigt auch den Umgang mit this:super(). Alle Attribute, für die sich die überschriebene Methode :set() nicht zuständig fühlt, sollten an die Superklasse delegiert werden, so dass irgendwann die vordefinierte Methode :set() das Setzen dieser Attribute durchführt.

Der Wert des Parameters Value wird auf jeden Fall berücksichtigt und dem Attribut zum Schluss zugewiesen. Das obige Beispiel könnte deswegen auch so geschrieben werden:

Beispiel

window {
  :set()
  {
    if Attribute = .title then
      Value := “<” + Value + “>”;
      OtherObject.title := “<” + Value + “>”;
    endif
    this:super();
  }
}

Erzwingen von rekursiven Aufrufen

Soll die Methode :set() für das selbe Objekt nochmals mit den veränderten Werten aufgerufen werden, so kann mit der Methode :recall() erzwungen werden, dass der Aufruf der als Parameter übergebenen :set()-Methode auch rekursiv stattfindet. Es ist jedoch Vorsicht geboten, da es auf diese Weise sehr leicht zu Endlosrekusionen kommen kann.

Beispiel

dialog SET

model record MRec {
  integer MaxCount:=100;
  integer Count:=0;
  :set()
  {
    variable boolean RetVal := true;

    case (Attribute)
    in .Count:
      if this.MaxCount < Value then  // Konsistenzprüfung.
        Value := this.MaxCount;      // Value korrigieren.
      endif;
      RetVal := this:super();
    in .MaxCount:
      if this.MaxCount > Value then
        this.MaxCount := Value;
        this:recall(:set, .Count, Value);
          // .Count auf Value setzen, wobei :set() nochmals aufgerufen wird.
        RetVal := true;
      else
        RetVal := false;             // Setzen ablehnen.
      endif
    otherwise:
      RetVal := this:super();
    endcase
    return RetVal;
  }
}

MRec Rec {
}

on dialog start {
  print Rec.Count;      // Sollwert = 0
  Rec.Count := 110;
  print Rec.Count;      // Sollwert = 100

  print Rec.MaxCount;   // Sollwert = 100
  Rec.MaxCount := 200;
  print Rec.MaxCount;   // Sollwert = 100
  Rec.MaxCount := 10;
  print Rec.MaxCount;   // Sollwert = 10
  print Rec.Count;      // Sollwert = 10
  exit();
}

Siehe auch

Eingebaute Funktion setvalue() im Handbuch „Regelsprache“

C-Funktion DM_SetValue im Handbuch „C-Schnittstelle - Funktionen“