Methodenaufruf
Um einen Methodenaufruf zu implementieren, werden den Schnittstellenvariablen die tatsächlichen Parameter (Argumente) übergeben. Dabei kann alternativ auf die Parameternamen verzichtet werden.
Je nach deklariertem Zugriffsmodifizierer kann eine Methode nur innerhalb des eigenen Namensraums (INTERNAL), nur innerhalb des eigenen Programmierbausteins und seinen Ableitungen (PROTECTED) oder nur innerhalb des eigenen Programmierbausteins (PRIVATE) aufgerufen werden. Bei PUBLIC kann die Methode überall aufgerufen werden.
Innerhalb der Implementierung kann eine Methode sich selbst rekursiv aufrufen: entweder direkt mit Hilfe des THIS-Pointers oder mit Hilfe einer lokalen Variablen für den zugeordneten Funktionsbaustein.
Methodenaufruf als virtueller Funktionsaufruf
Durch Vererbung kann es zu virtuellen Funktionsaufrufen kommen. Virtuelle Funktionsaufrufe ermöglichen, dass derselbe Aufruf in einem Programm-Quellcode während der Laufzeit verschiedene Methoden aufruft.
In folgenden Fällen wird der Methodenaufruf dynamisch gebunden:
- Sie rufen eine Methode über einen Pointer auf einen Funktionsbaustein auf (zum Beispiel pFB^.SampleMethod).
Der Pointer kann in dieser Situation auf Instanzen vom Typ des Funktionsbausteins und auf Instanzen von allen abgeleiteten Funktionsbausteinen zeigen. - Sie rufen eine Methode einer Schnittstellen-Variablen auf (zum Beispiel iSample.SampleMethod).
Die Schnittstelle kann auf alle Instanzen von Funktionsbausteinen verweisen, die diese Schnittstelle implementieren. - Eine Methode ruft eine andere Methode desselben Funktionsbausteins auf. Die Methode kann in dem Fall auch die Methode eines erweiterten Funktionsbausteins mit gleichem Namen aufrufen.
- Der Aufruf einer Methode erfolgt über eine Referenz auf einen Funktionsbaustein. Die Referenz kann in dieser Situation auf Instanzen vom Typ des Funktionsbausteins und auf Instanzen von allen abgeleiteten Funktionsbausteinen zeigen.
- Sie weisen VAR_IN_OUT-Variablen eines Basis-Funktionsbaustein-Typen einer Instanz eines abgeleiteten FB-Typen zu.
Die Variable kann in dieser Situation auf Instanzen vom Typ des Funktionsbausteins und auf Instanzen von allen abgeleiteten Funktionsbausteinen zeigen.
Beispiel
- Die Funktionsbausteine FB_Sub1 und FB_Sub2 erweitern jeweils den Funktionsbaustein FB_Base.
- FB_Base implementiert die Schnittstelle I_Base, die die Methode Method1 definiert.
- FB_Base und FB_Sub1 stellen jeweils die Methode Method1 zur Verfügung. FB_Sub1 überschreibt bzw. erweitert somit die Methode der Basisklasse FB_Base.
- FB_Sub2 stellt die Methode nicht zur Verfügung. Der Funktionsbaustein nutzt unverändert die Methode der Basisklasse FB_Base.
- In dem Programm MAIN wird einer Schnittstellenvariablen und einer Referenz auf die Basisklasse jeweils eine Instanz der Basisklasse FB_Base, eine Instanz der Unterklasse FB_Sub1 oder eine Instanz der Unterklasse FB_Sub2 zugewiesen. Welche Instanz zugewiesen wird, hängt von dem Wert der Variablen nVar ab.
- Über die Schnittstellenvariable und über die Referenzvariable wird die Methode Method1 aufgerufen. Dieser Methodenaufruf ist dynamisch und kann für unterschiedliche Instanzen (fbBase, fbSub1, fbSub2) ausgeführt werden, wobei sich die dahinterstehenden Methodenimplementierungen zwischen den Instanzen unterscheiden.
- Für die Instanz fbBase wird die Implementierung von FB_Base.Method1 ausgeführt.
- Für die Instanz fbSub1 wird die Implementierung von FB_Sub1.Method1 ausgeführt, da FB_Sub1 die Methode der Basisklasse überschreibt bzw. erweitert.
- Für die Instanz fbSub2 wird die Implementierung von FB_Base.Method1 ausgeführt, da die Unterklasse FB_Sub2 die Methode der Basisklasse weder überschreibt noch erweitert, sondern unverändert nutzt.
Schnittstelle I_Base mit der Methode Method1:
INTERFACE I_Base
METHOD Method1
Funktionsbaustein FB_Base mit der Methode Method1:
FUNCTION_BLOCK FB_Base IMPLEMENTS I_Base
METHOD Method1
Funktionsbaustein FB_Sub1 mit der Methode Method1:
FUNCTION_BLOCK FB_Sub1 EXTENDS FB_Base
METHOD Method1
Funktionsbaustein FB_Sub2 ohne eigene Methode:
FUNCTION_BLOCK FB_Sub2 EXTENDS FB_Base
Programm MAIN:
PROGRAM MAIN
VAR
nVar : INT;
fbBase : FB_Base;
fbSub1 : FB_Sub1;
fbSub2 : FB_Sub2;
iBase : I_Base;
refBase : REFERENCE to FB_Base;
END_VAR
(* Choosing the desired instances via value of nVar:
0 => fbBase
1 => fbSub1
2 => fbSub2 *)
IF nVar = 0 THEN
iBase := fbBase;
refBase REF= fbBase;
ELSIF nVar = 1 THEN
iBase := fbSub1;
refBase REF= fbSub1;
ELSIF nVar = 2 THEN
iBase := fbSub2;
refBase REF= fbSub2;
END_IF
// Regarding each of the following two calls via interface and via reference:
// If nVar is 0, FB_Base.Method1 will be called for instance fbBase
// If nVar is 1, FB_Sub1.Method1 will be called for instance fbSub1
// If nVar is 2, FB_Base.Method1 will be called for instance fbSub2
iBase.Method1();
refBase.Method1();
Zusätzliche Ausgänge
Gemäß der Norm IEC 61131-3 können Methoden sowie normale Funktionen zusätzliche Ausgänge deklariert haben. Beim Methodenaufruf weisen Sie den zusätzlichen Ausgängen Variablen zu.
Genaue Informationen hierzu finden Sie unter Objekt Funktion.
Methode rekursiv aufrufen
Hinweis | |
Verwenden Sie Rekursionen vorwiegend zur Bearbeitung von rekursiven Datentypen wie beispielsweise verketteten Listen. Allgemein ist es ratsam, bei der Verwendung von Rekursion vorsichtig zu sein. Bei einer unerwartet tiefen Rekursion kann es zu einem Stacküberlauf und damit zu einem Maschinenstillstand kommen. |
Innerhalb ihrer Implementierung kann eine Methode sich selbst aufrufen:
- direkt mit Hilfe des THIS-Pointers
- indirekt mit Hilfe einer lokalen Funktionsbaustein-Instanz des Basisfunktionsbausteins
Üblicherweise wird bei einem solchen rekursiven Aufruf eine Compilerwarnung ausgegeben. Wenn die Methode mit dem Pragma {attribute 'estimated-stack-usage' := '<estimated stack size in bytes>'} versehen ist, wird die Compilerwarnung unterdrückt. Im Kapitel Attribut 'estimated-stack-usage' finden Sie ein Implementierungsbeispiel.
Siehe auch:
- Objekt Methode
- Objekt Funktion
- Erweitern eines Funktionsbausteins
- Referenz Programmierung: SUPER
- Referenz Programmierung: THIS