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.
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“