====== Konzept: optional ====== Ein Pointer ist im Prinzip nur eine optionale Referenz (sofern nicht für Pointer-Arithmetik verwendet) optional wird mit einem "?" hinter dem Datentyp ausgedrückt, vgl. C#. p is Person; p is Person ref; // shared_ptr< Person > (ifc::ref) p is Person ref?; // opt_shared_ptr< Person > (darf null sein) (ifc::refopt) p is Person ptr; // Person & (value!!, muss gesetzt sein, erlaubt Pointer-Arithmetik) p is Person ptr?; // Person * (value!!, darf null sein, erlaubt Pointer-Arithmetik) p is Person link; // Person & p is Person link?; // Person * (als Referenz, darf null sein) p is Person{}; // Liste p is Person[]; // Liste p is Person ref?[]; // Liste (Referenz auf shared_ptr< Person * > (Referenz)) p is Person ptr[]; // Liste (list< Person * >) (Value)) p is Person link[]; // Liste (list< Person & >) p is Person link[]?; // Liste (listopt< Person & >) p is Person link?[]?; // Liste (listopt< Person * >) Eine Klasse, die flat ist, enthält keine verlinkten Daten. Alles, was optional, muss mit validate kontrolliert werden. Damit wird ptr quasi verteufelt, ist dann aber wieder Value-Type! Eine Klasse, die keine gelinkten Daten enthält, kann flat kopiert werden. Eine Klasse, die gelinkte Daten besitzt, muss Deep kopiert werden. Ein Member vom Typ "Person link" wird bei einer Kopie der Klasse mitkopiert und erhält einen neuen Zeiger. Pointer sollten entsprechend nicht verwendet werden. Um optionale Daten zu halten, sollten links verwendet. Ein link ist quasi ein einstelliges Array/Liste und sollte auch als solches behandelt werden können. pl is Person link : new ("Sascha", "Atrops" ); pa is Person{} : pl; Ein Enum/Flag ist ein konstanter Zeiger auf das jeweilige Objekt. enum Boolean : bool { True( true ) is default, False( false ); }; b is Boolean; // ( Boolean const & ) Zu überlegen wäre noch ein "Person paired", das auf ein "new paired Person" verweisen kann. Das Ding würde sich eigentlich als "link" anbieten. In jedem Fall sollte so ein "paired" sich in ein Array des zu verlinkten Objektes eintragen. Ein Link ist damit nicht responsible. Wird das Objekt über ein responsible link gelöscht, werden alle paired links auf Null gesetzt. ====== new/delete, shared ====== **New liefert einen optionalen Pointer zurück:** p is Person ptr?( new Person( "Sascha", "Atrops" ) ); // oder func is code := { p is new Person( "Sascha", "Atrops" ); validate( p ) p.print(); delete p; // p muss manuell freigegeben werden } // p wird verworfen **shared liefert eine optionale Referenz zurück** func is code := { p is Person ref?; p : shared Person( "Sascha", "Atrops" ); // oder p is shared Person( "Sascha", "Atrops" ); validate( p ); p.print(); }; // p wird automatisch freigegeben In Kombination mit [[notes:func:guard|guards]]: func is code := { guard( "Konnte Person nicht deklarieren" ) p is shared Person( "Sascha", "Atrops" ); p.print(); // Solange p nur mit schreibgeschützten Funktionen gerufen wird, kann nix passieren }; // p wird automatisch freigegeben **Arrays** Ein Array entspricht einem C-Array func is code := { array is byte{8}; array[0] = 'G'; array[1] = 'e'; array[2] = 'n'; array[3] = 'e'; array[4]= 's'; array[5] = 'y'; array[6] = 's'; array[7] = null; print array$; } // liegt auf dem Stack **Listen** Eine Liste ist eine per Referenz vorwärtsverkettet und per link zurück. Die Elemente sind shared. Das führt dazu, dass auch Teilkonstrukte weitergeben werden können: [first tail] : list; oder printlist is code( [first tail] is int[] ) := { // first is int link?, tail ist int[] ref? ) validate first { print first$; printlist( tail ); } } printlist( [1, 2, 3} ); Das Anlegen einer Liste ist grundsätzlich mit einem guard begleitet. Sollte der Guard vom Entwickler nicht angegeben sein, endet die Funktion mit einer System-Fehlermeldung. func is code := { array is byte[8]; array[0] = 'G'; array[1] = 'e'; array[2] = 'n'; array[3] = 'e'; array[4] = 's'; array[5] = 'y'; array[6] = 's'; array[7] = null; print array$; } // liegt auf dem Stack **Vectoren** Ein Vector kann shared sein - muss er aber nicht. func is code := { array is byte<8>; array[0] = 'G'; array[1] = 'e'; array[2] = 'n'; array[3] = 'e'; array[4] = 's'; array[5] = 'y'; array[6] = 's'; array[7] = null; print array$; } // liegt auf dem Stack