# Attribut- und Methodenzugrif in ST (objektorientierte Programmierung)



## buzzer (29 Juli 2014)

Hallo zusammen,

Derzeit sitze ich an einem Projekt mit einer WAGO 767-2301, die Messwerte sammeln soll. Da ich bereits einiges objektorientiert programmiert habe (Java,C++, Matlab), möchte ich dies auch hier umsetzen. Die Übersichtlichkeit, Stabilität und Wartbarkeit wird durch OOP meiner Meinung nach stark gefördert. Leider stieß ich bereits am Anfang auf Probleme.

Was ich bisher habe: Steuerung, Bus etc. funktionieren einwandfrei mit klassischer Programmierung. Da das Projekt einige Slaves umfasst, soll über Klasseninstanzen die Buskommunikation gesteuert werden. Eine weitere Klasse soll Hilfsfunktionen zur Verfügung stellen. Bei CoDeSys 3.4.4 ist OOP im Menü aktiviert worden und ich habe die Funktionsbausteine mit Methoden und Attributen versehen.

Nun das Problem: Zugriffe und Zuweisungen mit THIS.meineFunktion/Attribut/Variable oder _meineFunktion/Attribut innerhalb der Klasse produzieren Fehlermeldungen: 
unbekannter Typ  - bzgl. Rückgabewert einer Methode
'THIS' ist keine Strukturvariable  // Bei Attributen sowie VAR (ohne Namenskonflikte)
_Wie verweise ich korrekt auf die Attribute und Methoden der zugehörigen Instanz? Muss ich ansonsten die Instanz der Methode separat als VAR_INPUT übergeben?
Wie sollte eine simple Getter oder Setter Methode in ST aussehen? (Keine Prüfung oder ä., nur simples Lesen/Schreiben)_
Die Autovervollständigung bietet bei THIS.* bereits die Methoden etc. an. Einige Beispiele aus verschiedenen Dokumenten habe ich bereits gefunden, komme aber an dieser wichtigen Stelle nicht weiter.

Eine weitere Frage:
Der Buszugriff (Modbus) erfolgt über die CoDeSys Treiber. Jeweils ein Eingags/Ausgangs-Wort wurde damit einer lokalen Variable zugeordnet. Dies funktioniert soweit. Nun möchte ich gerne den Buszugriff komplett innerhalb der Klasse abarbeiten. _Ist dies möglich indem ein POINTER TO WORD auf meine Busvariable gesetzt wird, welche ich anschließend meiner Klasse übergebe? _

Ich hoffe das Problem ist verständlich geschildert und ich bin für jede Hilfe dankbar.


----------



## Werner29 (29 Juli 2014)

Hallo,

ganz einfach: THIS ist ein Pointer und muss dereferenziert werden mit ^.
Also THIS^.variable sollte dir den Zugriff auf die Methoden und Member liefern.

THIS^ kann im Übrigen auch weggelassen werden.




buzzer schrieb:


> Eine weitere Frage:
> Der Buszugriff (Modbus) erfolgt über die CoDeSys Treiber. Jeweils ein Eingags/Ausgangs-Wort wurde damit einer lokalen Variable zugeordnet. Dies funktioniert soweit. Nun möchte ich gerne den Buszugriff komplett innerhalb der Klasse abarbeiten. _Ist dies möglich indem ein POINTER TO WORD auf meine Busvariable gesetzt wird, welche ich anschließend meiner Klasse übergebe? _



Wenn du auf die Ein/Ausgänge über POINTER zugreifst, dann weiss der Treiber nicht, in welcher Task der Zugriff erfolgt, es kann sein, dass dann das IO-Update nicht erfolgt.
Daher ist es geschickter die Ausgänge direkt auf eine Variablen in deiner Klasse zu legen mit map on existing in der Konfiguration.
Oder die Einstellung wählen: alle Ausgänge updaten.


----------



## Larry Laffer (29 Juli 2014)

@Werner:
Ich vermute, dass es dem TE vielmehr darum geht, wie er überhaupt seine Klasse (den FB) instanziert. Ich glaube nicht, das THIS die Instanz des Bausteins sein soll. Leider bin ich absolut kein Codesys'er um das beantworten zu können ...

Gruß
Larry


----------



## buzzer (29 Juli 2014)

die Hinweise von Werner haben mich schon ein ordentliches Stück weitergebracht. THIS habe ich dementsprechend weggelassen. War es zuletzt von Matlab gewöhnt dieses zu verwenden. Auch verwende ich ich statt Eigenschaften/Properties vorerst wieder die Deklaration als VAR. Der Grund ist, dass der Zugriff auf Arrays und Structs dafür umständlich scheint und ich weitere Syntaxfehler vermeiden will. Werde mir morgen mal die Samples aus dem CoDeSys Shop ansehen um daraus zu lernen. Insbes. zu den Getter/Setter Methoden hatte ich nocht nicht viel gesehen.
Die Instanzierung und inzwischen der Methodenaufruf erfolgt problemlos wie bei normale FBs. Es war tatsächlich der aufgezeigte Syntaxfehler.

Das ich mit map on existing die Buszugriffe direkt auf Objektvariablen legen kann hatte ich nicht erwartet. Finde ich aber sehr praktisch und werde es testen.

Schon mal vielen Dank für die Informationen.


----------



## Werner29 (30 Juli 2014)

Bei Properties die Arrays oder Strukturen zurückliefern, muss man aufpassen: die Struktur wird dann wirklich als Wert zurückgeliefert und dementsprechend mehrmals umkopiert.
Ein Schreiben in die zurückgelieferte Struktur ändert dementsprechend nicht das Original in der Klasse, sondern die kopierte Struktur.

Wenn man direkten Zugriff auf ein Array oder eine Struktur in der Klasse bieten will, dann sollte man eine Referenz auf die Variable zurückliefern

PROPERTY Arr_prop : REFERENCE TO ARRAY[0..5] OF STRUCT_1

Und im Getter:
Arr_prop REF= loc_var;


Ein Setter ist dann nicht notwendig, bzw. eher schädlich, denn ein schreibender Zugriff ist auch über die Referenz möglich

fb.Arr_prop[2].compo := 10;

mit so einem Zugriff wird dann direkt die Variable loc_var manipuliert.


----------



## Interface (1 August 2014)

Werner29 schrieb:


> Ein Setter ist dann nicht notwendig, bzw. eher schädlich, denn ein schreibender Zugriff ist auch über die Referenz möglich
> 
> fb.Arr_prop[2].compo := 10;
> 
> mit so einem Zugriff wird dann direkt die Variable loc_var manipuliert.


Gibt es eine Möglichkeit, diesen Schreibzugriff auf die lokale Variable zu verhindern?
Ich möchte über Interface-Properties auf Strukturelemente direkt zugreifen - aber nur lesend.


----------



## buzzer (4 August 2014)

Bei mir habe ich vorerst auf vollständige Datenkapselung verzichtet. Indem ich die Klassen und Methoden nur per CFC verbinde hilft das Funktionsblockprinzip ebenfalls ungünstige Zugriffe zu vermeiden.
Den ^.THIS Ausdruck verwende ich inzwischen wieder um zwischen gleichnamigen Variablen in Objekt und Methode zu unterscheiden.


----------



## Werner29 (4 August 2014)

Interface schrieb:


> Gibt es eine Möglichkeit, diesen Schreibzugriff auf die lokale Variable zu verhindern?
> Ich möchte über Interface-Properties auf Strukturelemente direkt zugreifen - aber nur lesend.



Nein das geht im Moment nicht. Wenn man eine Referenz rausreicht, dann besteht voller Zugriff.


----------

