====== Identifier definitions ====== Einen Identifier kann man auf verschiedene Weise erzeugen. Zu unterscheiden sind vier Typen * Gleichsetzung (alias, typedef, static const, enum, flag) * Definition einer Variablen/Member * Definition eines Typs mit Variablendefinition ===== Konstanten ===== Konstanten werden einfach mit '=' gesetzt: a = 4; b = int(4); p = Point(1, 2, 3); Point contains { x, y, z is double; // Variablen construct( as x, as y, as z ); Origin = Point( 0, 0, 0 ); // Konstante } ===== statische Funktionen ===== ...sind im Prinzip wie Konstanten, nur dass die Identifier von Parametern abhängig sind: add( a, b is int ) = a+b; ===== Funktionszeiger ===== add( a, b is int ) = a+b; // Konstante addref is code( a, b is int ) (add); // Variable ===== Typedefs ===== Typedefs entsprechen im Prinzip Konstanten, da sie statisch sind und nicht verändert werden können. MyInt = int; funcType = code( int a, int b) as int; ===== enums und flags ===== sind konstante Werte und werden direkt zugewiesen: enum Color { Rot = 0xFF0000, Gruen = 0x00FF00, Blau = 0x0000FF }; ===== Definitionen einer Variablen ===== Definitionen werden mit 'is' beschrieben Variabeln können im Gegensatz zu Konstanten überschrieben werden. a is int; t is type; i is 0; // int j is int(0); // int p is Point( 1, 2, 3 ); ===== alias ===== Aliase sind funktionsinterne Namen, bzw. Abkürzungen. Auto contains { Farbe, Hersteller; construct( f = .Farbe, h = .Hersteller ) := print "Das neue Auto ist %s und wird von %s gebaut\n" % ( f%, h$ ); } add( summand1 = s1, summand2 = s2 as int ) = s1+s2; ===== Typedef mit automatischer Variablendeklaration ===== Count is discrete int(4711); int integer = 7328; User contains { Id is discrete int; // erzeugt den Typ User::Id, der von int erbt. Name is string; // einfache String-Variable staticValue = 0; construct( construct .Id, .Name ); // String wird 1:1 durchgeschleift, // Id darf konstruiert werden, es dürfen also auch explizite // Konstruktoren von Id gerufen werden, z.B. Id( int ) // Der erste Parameter muss auf einen Konstruktor von Id passen (also Id oder int) // Hat der Konstruktor mehrere Parameter, darf geklappert werden. Der Aufruf muss nicht Id( 1, 2) sein, // sondern (1, 2) reicht, wenn er erste Parameter - eben (1,2) - auf einen Id-Construktor passt. { // nothing to do // Aufruf User( User::Id( 1 ), "Peter" ) // Aber auch User( 2 /* da construct id */, "Gustav" ); // auch User( integer /* da construct id */, , "Heinrich" ) // NICHT User( Count, "Markus" ) // da Count discrete ist und Id keinen Konstruktor für Count hat } construct( .Id ) { .Name : Id$; // Aufruf User( User::Id(2) ) ok // Aufruf User( cast 2 ), User( cast integer ) // Aufruf User( cast Count ) // nicht ok, cast Count wäre z.B. int, aber es steht ist kein Cast für User::Id definiert. (müsste man erklären) // Aufruf User( 2 ) geht nicht, da Id kein int mehr ist und explizit konstruiert werden muss // Aufruf User( integer ), User( Count ) geht beides nicht // Aufruf User( User::Id( cast Count ) ) ok // User::Id verlangt int, cast Count kann int liefern } construct( a is Id ) // Variable vom Typ Id { .Id : a; // Eventuell erst Standard-Konstruktor, dann operator = .Name : a$; // Aufruf User( User::Id(2) ) ok // Aufruf User( 2 ) nopes // Aufruf User( staticValue ) // nopes // Aufruf User( cast integer ), // ok // Aufruf User( cast Count ) nopes } construct( a is Id ) // Variable vom Typ Id { .Id = a; // Eventuell erst Standard-Konstruktor, dann operator = .Name = a$; // Aufruf User( User::Id(2) ) ok // Aufruf User( 2 ) nopes // Aufruf User( staticValue ) // nopes // Aufruf User( cast integer ), // ok // Aufruf User( cast Count ) nopes } }; ===== Initialisierung ===== Der = Operator ersetzt die Initialisierungsliste. Das ermöglicht einen Programmablauf, bevor Membervariblen initialisiert sind. User contains { Id is discrete int; // erzeugt den Typ User::Id, der von int erbt. Name is string; // einfache String-Variable construct( id is Id, name is Name ) { .Id = id; // Standardkonstruktor für .Id wird nicht aufgerufen, sondern Copy-Construktor .Id = User::Id( 1 ); // Fehler: Initialisiert wird nur einmal .Name : name; // Standardkonstruktor, dann Zuweisung. Hint: Könnte auch über Initialisierung laufen .Name = "Name"; // Fehler: .Name wurde schon per Standardkonstruktor initialisiert. } // besser construct( .Id, .Name ); };