Twincat: Function Block-EXTENDS funktioniert nicht in Arrays?

Beiträge
9
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo zusammen,

ich bin auf ein Verhalten in Twincat gestoßen, das ich im Grunde für einen Bug halte. Vielleicht übersehe ich aber einfach irgendwas?

Ich habe zwei Function Blocks, FB_Parent und FB_Child. Letzteres EXTENDS ersteres. Beide haben je eine Methode, die ein Integer zurückliefert, die Child-Methode (Rückgabe "2") überschreibt also die Parent-Methode (Rückgabe "1").

Das funktioniert genau wie erwartet, solange ich die beiden Function Blocks nicht in ein Array schreibe:

MAIN:

Code:
PROGRAM MAIN
VAR
    fbParent : FB_Parent;
    fbChild : FB_Child;
    aFBArray : ARRAY[1..2] OF FB_Parent := [fbParent, fbChild];
    
    nParentDirect : INT;
    nChildDirect  : INT;
    nParentArray  : INT;
    nChildArray   : INT;
END_VAR
_______________________________________________________________________

nParentDirect := fbParent.M_Method();
nChildDirect  := fbChild.M_Method();
nParentArray  := aFBArray[1].M_Method();
nChildArray   := aFBArray[2].M_Method();

Function Block Parent:
Code:
FUNCTION_BLOCK FB_Parent
________________________________________________________________________
METHOD M_Method : INT
________________________________________________________________________
M_Method := 1;

Function Block Child:
Code:
FUNCTION_BLOCK FB_Child EXTENDS FB_Parent
________________________________________________________________________
METHOD M_Method : INT
________________________________________________________________________
M_Method := 2;

Ausgabe:

nParentDirect := 1
nChildDirect := 2
nParentArray := 1
nChildArray := 1

Man beachte die letzte Zeile. nChildArray wird erzeugt aus aFBArray[2], wo eigentlich fbChild abgelegt sein sollte. Der Rückgabewert, den ich erwarte, ist 2.

Ich kann also ohne Fehlermeldung fbParent und fbChild in ein Array packen, aber dann wird aus Child wieder Parent.

Ich kriege das ganze zum Laufen, indem ich stattdessen ein Interface definiere und auf Vererbung von Parent zu Child verzichte, aber das ist auch nicht ideal, weil ich dann Code doppelt ablegen muss, der normalerweise vererbt würde. Das Interface ist ja ohnehin schon eine Doppelung der Header des Function Blocks, und ich möchte doppelten Code soweit wie möglich vermeiden.

Ist das einfach so, oder mache/denke ich was falsch?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
FB-Instanzen sind keine Referenzen, sondern statische Variablen des FB-Typs. Die Zuweisung eines fbChild an eine statische fbParent-Instanz ist zwar möglich, aber dabei wird aus dem fbChild natürlich wieder ein fbParent.
Du müsstest in dem Array schon mit Zeigern auf fbParents arbeiten. Die werden aber, im Gegensatz zu Interfaces, bei einem Online-Change nicht automatisch mitgezogen.
Wenn Du im PC-Hochsprachenstil OOP programmieren willst, kommst Du in TwinCat/CodeSys deshalb an Interfaces nicht vorbei.
 
Ich denke das liegt daran, dass du ein Array vom Typ FB_Parent anlegst. Dort übergibst du den FB_Child.
Mich wundert mehr, dass der Compiler das zulässt.
Genau. Wenn der Compiler da meckern würde, wäre es zumindest in sich stimmig. Andererseits ist es ja gerade der Sinn von Vererbung, dass sich Objekte von Kindklassen nach außen verhalten wie ein Objekt der Elternklasse. So kann man die Logik im Objekt kapseln, das heißt, das Objekt weiß selber, dass es einen anderen Programmcode ausführen muss, ohne dass das Hauptprogramm das wissen müsste.
 
FB-Instanzen sind keine Referenzen, sondern statische Variablen des FB-Typs. Die Zuweisung eines fbChild an eine statische fbParent-Instanz ist zwar möglich, aber dabei wird aus dem fbChild natürlich wieder ein fbParent.
Du müsstest in dem Array schon mit Zeigern auf fbParents arbeiten. Die werden aber, im Gegensatz zu Interfaces, bei einem Online-Change nicht automatisch mitgezogen.
Wenn Du im PC-Hochsprachenstil OOP programmieren willst, kommst Du in TwinCat/CodeSys deshalb an Interfaces nicht vorbei.
Okay, dann treibe ich mit den Interfaces zumindest keinen unnötigen Aufwand.

Habe den Code jetzt folgendermaßen geändert (nur geänderte Zeilen):

Code:
INTERFACE I_Parent
____________________________________
METHOD M_Method : INT

Code:
FUNCTION_BLOCK FB_Parent IMPLEMENTS I_Parent

Code:
FUNCTION_BLOCK FB_Child EXTENDS FB_Parent IMPLEMENTS I_Parent

Code:
PROGRAM MAIN
[...]
aFBArray : ARRAY[1..2] OF I_Parent := [fbParent, fbChild];

Das ergibt den erwünschten Output :) Danke Euch!
 
Zurück
Oben