Tc3: Vererbung von Aktionen

StructuredTrash

Level-3
Beiträge
1.171
Reaktionspunkte
312
Ich bin zwar mit TwinCat unterwegs, aber mein Problem ist wohl eher eine Codesys-Sache. Die Experten von 3S sind daher herzlich zum Mitlesen eingeladen.
Ich deklariere zwei FBs:
Code:
FUNCTION_BLOCK fblBase
VAR_INPUT
    inpBase:BOOL;
END_VAR
und
Code:
FUNCTION_BLOCK fblExtd EXTENDS fblBase
VAR_INPUT
    inpExtd:BOOL;
END_VAR
"fblBase" hat eine Aktion "pubBaseActn".
Im Hauptprogramm deklariere ich von jedem FB eine Instanz
Code:
PROGRAM MAIN
VAR
    varBase:fblBase;
    varExtd:fblExtd;
END_VAR
und rufe beide Aktionen auf
Code:
varBase.pubBaseActn(
    inpBase:=TRUE);
varExtd.pubBaseActn(
    inpBase:=TRUE,
    inpExtd:=TRUE);
Beim Übersetzen erhalte ich für den Aufruf von "varExtd.pubBaseActn" den Fehler "inpExtd ist kein Eingang von fblBase".
Sicher, der FB, von dem die Aktion geerbt wurde, kennt "inpExtd" nicht. Ich rufe aber ausdrücklich eine Instanz von "fblExtd" auf, die diese Variable beinhaltet.
Ist das wirklich so gewollt? Mir ist schon klar, dass so etwas bei unterschiedlich grossen VAR_IN_OUT-Bereichen nicht funktionieren kann, weil die geerbten Aktionen für die Stackgrösse der Basisklasse kompiliert sind.
Aber hier handelt es sich um eine statische Variable des FBs. Wenn ich es so schreibe,
Code:
varExtd.inpExtd:=TRUE;
varExtd.pubBaseActn(
    inpBase:=TRUE);
funktioniert es ja. Und an sich sollte doch beides identisch sein.
 
Du hast dir die Antwort eh schon selbst gegeben. In der Signatur vom Extd Baustein ist diese Var nicht vorhanden, deshalb geht es nicht. Das gleiche Problem hast du ja auch bei den Methoden. Ich glaube die S3 Jungs sträuben sich ein wenig vor dem Ändern der Signaturen einer Methode, Bausteins beim Vererben, da das raussuchen der richtigen Methode beim Aufruf Zeit kostet => siehe Unterschied C, C++.
 
Der Grund liegt in den Unterschiedlichen Möglichkeiten der Vererbung. Die Aktion wird vererbt - und du kannst sie auch überschreiben. Was du aber versuchst, ist ein ÜBERLADEN, nämlich die selbe Funktion mit verschiedenen Parametern zu verwenden - und das geht eben bei Codesys nicht.
 
Alles richtig, soweit es sich um Daten handelt, die beim Aufruf über den Stack übergeben werden, also Parameter von Methoden oder auch VAR_IN_OUT eines FBs. Ich versuche jedoch, bei (oder genauer gesagt vor) dem Aufruf der Aktion statische VAR_INPUT des FBs zu beschreiben, was seit Jahrhunderten gang und gäbe ist. Warum sich die "Bekanntheit" der Variablen dabei nach der Basisklasse der aufgerufenen Aktion und nicht nach der FB-Instanz richtet, ist mir nicht klar. Ich kenne den internen Aufbau von Codesys nicht, es kann durchaus sein, dass die interne Struktur dies nicht oder nur unter für 3S unzumutbaren Schmerzen ermöglicht. Vielleicht ist es aber auch nur ein Versehen und wird irgendwann noch mal geändert. Oder es ist eine Philosophie, dann wird sich daran wohl nichts mehr ändern.
 
Grundsätzlich sind die Aktionen ja auch eigentlich als parameterlose Methoden definiert - weshalb dein Vorgehen zwar funktioniert, aber eigentlich unlogisch ist. Der eigentlich logische Weg wäre folgendes:
Code:
varExtd.inpExtd:=TRUE;
varExtd.inpBase:=TRUE;
varExtd.pubBaseActn();
oder
Code:
varExtd(inpExtd:=TRUE, inpBase:=TRUE);
varExtd.pubBaseActn();
alles andere ist mMn unsauber und verwirrend, weil die Definitionen von Aktionen und Methoden durcheinander gewürfelt werden. Ich verstehe, dass man das aus Gründen der Kompatibilität erhalten musste, aber ein derartiges Konstrukt auch noch anzupassen halte ich für nicht sinnvoll.
 
Grundsätzlich sind die Aktionen ja auch eigentlich als parameterlose Methoden definiert - weshalb dein Vorgehen zwar funktioniert, aber eigentlich unlogisch ist.
Das sehe ich nicht so. Aktionen sind keine Methoden und auch nicht grundsätzlich parameterlos (Stichpunkt VAR_IN_OUT). Der Umstand, dass sie nun auch vererbt werden, und die vergleichbare Aufruf-Schreibweise dürfen nicht darüber hinwegtäuschen, dass Aktionen eher alternative FB-Aufrufe sind. Und genauso wie bei einem FB-Aufruf kann ich davor beliebige VAR_INPUT des FB beschreiben.
Dieser Aufruf
Code:
varExtd.pubBaseActn(
   inpBase:=TRUE,
   inpExtd:=TRUE);
ist doch nur eine einfachere Schreibweise für
Code:
varExtd.inpBase:=TRUE;
varExtd.inpExtd:=TRUE;
varExtd.pubBaseActn();
Dass dies bei geerbten Aktionen nicht mehr in vollem Umfang möglich ist, empfinde ich als unnötige Einschränkung.
 
Okay, sagen wir es anders: Aktionen übergabeparameterlose und rückgabeparameterlose (ja, sie sind parameterlos, denn jeder Parameter wie auch die var_in_out sind eigentlich dem Funktionsbaustein und nicht der Aktion zugeordnet) Funktionen mit Zugriff auf funktionsbausteininterne Variablen.
Man kann sie natürlich als alternativen Aufruf benutzen, aber das wäre sehr kurz gedacht, weil sie ja auch deutlich mehr können (gekapselte Funktion, im FB selbst in verschiedenen Reihenfolgen aufrufbar etc.)

Trotzallem empfinde ich es ebenfalls als Einschränkung, dass die Signatur einer Methode (eine Aktion hat ja nur eine, weil sie keine Parameter hat) nicht geprüft wird, sondern lediglich der Bezeichner (und somit ein Überladen nicht möglich ist) - denn das ist in den meisten Hochsprachen schon vor Jahren möglich gewesen. Und ich vermute auch, dass das der Grund ist, warum es hier nicht geht - weil eben lediglich auf Namen geprüft wird (oder andersherum, vielleicht ist der Grund, dass es hier nicht geht der Grund, warum es bei Methoden auch nicht geht -> keine Ahnung)
 
Methoden überladen zu können, wäre schön. Dann würde ich gar nicht auf die Idee kommen, ersatzweise Aktionen zu benutzen, sondern diese nur noch als interne FB-Unterprogramme verwenden. Vielleicht wird's ja noch irgendwann mal in CodDeSys4. Bis dahin muss man halt aus den vorhandenen Mitteln das Beste machen.
 
Zurück
Oben