construct

Kurzconstructor

Point contains
{
  x, y is int;
  
  construct( x, y ); 
}

x und y sind bekannt, sie sind vom Typ her int, also ist das ein Point(int, int)-Konstruktor. Die Übergaben werden direkt ins neue Objekt kopiert. Im Idealfall läuft die Konstruktion so inline ab.

Default Argumente

Defaultargumente werden wie in C mit der Zuweisung erledigt.

Point contains
{
  x, y is int;
  
  construct( x:0, y:0 );
  construct( x = 0 as int, y = 0 as int ) :=  // hier sind x und y neue Konstanten, hier sollte eine Warning erfolgen
  {
    .x : x;
    .y : y;
  }

  construct( x is 0 as int, y is 0 as int ) :=  // hier sind x und y neue Variablen
  {
    x +: 1;
    y +: 1;
    
    .x : x;
    .y : y;
  }
}

Const-Objekte

Es ist zu überlegen, ob Objekte grundsätzlich Konstant zurückgegeben werden.

So würde

Point contains
{
  x, y is int;
  
  construct( x, y ); 
}

einen unveränderlichen Punkt zurückliefern. Damit wäre is eine reine Ableitung und verliert seine Bedeutung als mutable object. Wenn man auf 'class' geht könnte man mutable bzw. const einführen:

Point is const/var class
{
  x, y is int;
  
  construct( x, y ); 
}

um sich für die komplette Klasse festzulegen. Legt man sich nicht fest, könnte man nach OOP von einer mutable class ausgehen und const Konstruktoren definieren:

Point is class
{
  x, y is int;
  
  construct( x, y ) const; 
}

Da Genesys allerdings maximal restriktiv sein soll, könnnte man auch von einer konstanten Klasse per Default ausgehen:

Point contains
{
  x, y is int;
  
  construct( x, y ) var; 
}

construct as

Ein Konstruktor kann mit der as Anweisung Parameter gleich auf dem Zielspeicher initialisieren:

Rect contains
{
  Source is Point;  // erstellt expliziten construct( Point )
  Target is Point;  // erstellt expliziten construct( Point )
  
  construct( Point as Source, Point as Target ); 
  construct( Source, Target ); 
};

Der Construktor schreibt die übergebenen Punkte direkt nach Source bzw. Target. Erlaubt sind ( Point, Point ), aber auch ( Rect::Source, Rect::Target ). Hier findet im ersten Konstruktor ein expliziter Aufruf von Rect::Source::construct( Point ), bzw. Rect::Target::construct( Point ) statt. Im 2. Konstruktor wird ebenfalls nur durchgereicht, als Eingangstyp wird allerdings Rect::Source, bzw. Rect::Target verlangt.

new construct as

Müssen Berechnungen durchgeführt werden, so können temporäre Objekte mit as - Parametern verhindert werden. Sie werden direkt im neuen Objekt erstellt:

Statt:

Point contains
{
  XOffset is int;
  YOffset is int;
  
  construct( XOffset, YOffset )
};

offset as int : 4711;
x as int : offset + 10;
y as int : offset + 20;

p as Point ptr : new( x, y );

oder

Point contains
{
  XOffset is int;
  YOffset is int;
  
  construct( XOffset, YOffset ) :=
    print "Punkt ", XOffset$, "/", YOffset$, "konstruiert";
};

offset as int : 4711;

p as Point ptr : new( XOffset, YOffset )
{
  XOffset : offset + 10;
  YOffset : offset + 20;
}

Im zweiten Fall wird das Objekt erzeugt und es gibt einen gültigen Konstruktor ( XOffset, YOffset ). Der Konstruktor besteht aus zwei Teilen: Dem Initialisierungsbereich: der Zuweisung von XOffset und YOffset, die vor der print-Anweisung initialisiert werden; und eben dem Anweisungsblock mit dem Print.

new( XOffset, YOffset ) stellt klar, welcher Konstruktor verwendet wird. Alle im Konstruktor genannten Variablen müssen initialisiert werden. Anschließend wird der Anweisungsblock des Konstruktors gerufen. Die Initialisierung wurde bereits vom Benutzer übernommen.