Das ATOS-Magazin 3/99
ATOS Programmierpraxis
Moderne Zeiten
Definition der Schnittstelle

# automatische Prozedurwahl

Beim Anlegen eines Objektes muß ebenso wie beim Anlegen einer normalen Variablen der Typ angegeben werden. Bei einer solchen Deklaration wird sich ein Compiler oder Interpreter diesen Typ merken. GFA-Basic ist da ja bekanntlich seit eh und jeh recht faul und merkt sich in dieser Hinsicht in der Tat wirklich nichts. Man muß dem Basic jedesmal über das Postfix aufs neue mitteilen, von welchem Typ eine Variable ist. Der Vorteil ist eine teilweise bessere Lesbarkeit (man sieht dem Namen einer Variablen stets ihren Typ an) und -- nicht immer ein Vorteil --, daß man ein und den selben Bezeichner für verschiedene Typen wiederverwenden kann. Der große Nachteil ist jedoch, daß man bei Typänderungen (was häufig vorkommt, wenn der Wertebreich einer Variablen anfangs zu klein oder unnötig groß dimensioniert wurde) das komplette Listing ändernd durchlaufen muß.

Objektorientierte Sprachen setzen nun sozusagen "noch einen drauf": Sie ermöglichen beim Aufruf einer Funktion oder Prozedur die automatische Wahl der Funktion bzw. Prozedur abhängig vom Typ eines übergebenen Objektes.

So ist noch fast jeder "herkömmliche" Compiler oder Interpreter in der Lage, bei einer einfachen Addition anhand der Typen der zu addierenden Zahlen die optimale Operation zu wählen: Ganzzahladdition bei Ganzzahlen, Fließkommaaddition bei Fließkommazahlen usw. Als Programmierer schreibt man schlicht "`+`". Ändert man irgendwann die Typen der beteiligten Zahlen, wird automatisch wieder das dazu passende "`+`" gewählt.

Hier kann GFA-Basic sogar noch mithalten. Compiler und Interpreter für objektorientierte Sprachen ermöglichen aber eine automatische Wahl der richtigen Operation für beliebige Typen und Operationen, nicht nur bei der Addition von Zahlen.

Ein Beispiel:

Das Quadrat einer Fließkommazahl wird natürlich nicht auf die gleiche Weise errechnet, wie das einer Ganzzahl. Wollen wir zwei passende Quadrierfunktion in GFA-Basic implementieren, so benötigen diese unterschiedliche Namen:

    FUNCTION float_sqr(zahl#)
      RETURN zahl#*zahl#
    ENDFUNC
    FUNCTION int_sqr(zahl%)
      $F%
      RETURN MUL(zahl%,zahl%)
    ENDFUNC

Die Aufrufe lauten entsprechend

    PRINT @float_sqr(a#)
    PRINT @int_srq(b%)

In objektorientierten Sprachen kann man beide Funktionen gleich benennen. Durch ihre Position im Listing wird dem Compiler oder Interpreter mitgeteilt, welche Funktion zu welchem Typ gehört. Ein objektorientiertes Listing besteht ja nun, wie im ersten Kursteil angesprochen, nur aus Typbeschreibungen. Irgendwo findet sich dann eine Typbeschreibung für Objekte des Typs "float" und an anderer Stelle eine Beschreibung für Objekte des Typs "int". An diesen Stellen werden die Funktionen dann eingereiht:

    TYPE float
      FUNCTION sqr
        RETURN ob*ob
      ENDFUNC
    ENDTYPE
    TYPE int
      FUNCTION sqr
        $F%
        RETURN MUL(ob,ob)
      ENDFUNC
    ENDTYPE

Durch die Möglichkeit, das aktuelle Objekt auch über den Bezeichner "`ob`" anzusprechen (s.o.), spart man sich zudem diesen Eintrag in der Parameterliste. Die Aufruf lauten dann entsprechend in der Punktnotation:

    PRINT a.sqr
    PRINT b.sqr

Der große Vorteil liegt nun vor allen Dingen in der Syntax dieser Aufrufe. Es ist nicht notwendig, den Typ von `a` oder `b` beim Aufruf zu erwähnen. Ändert man nachträglich den Typ einer Variablen im Deklarationsteil, können die Aufrufe allesamt unangetastet bleiben. Der Compiler oder Interpreter stellt sich auf die Änderung ein und wählt entsprechend andere Prozeduren und Funktionen.

Bei der Definition unseres neuen Objekttyps "Fußballspieler" können wir leider nicht auf eine solche Fähigkeit von GFA-Basic zurückgreifen. Um einen vertretbaren Aufwand von Speicherplatz und Rechenzeit einzuhalten, bleibt leider nur die Lösung, jeder Prozedur in ihrem Namen mit auf den Weg zu geben, für welche Objekttypen sie gedacht ist.

Bei der Benutzung der OT/OB-Lib wurde nun vereinbart, Funktions- und Prozedurnamen stets mit dem Typbezeichner beginnen zu lassen. Deshalb tragen die Funktionen, die mit Fußballspielern "umgehen", alle das Präfix "`fussballspieler_`" im Namen:

    FUNCTION fussballspieler_name$(ob#)
    FUNCTION fussballspieler_tor(ob#)
    FUNCTION fussballspieler_abwehr(ob#)
    FUNCTION fussballspieler_mitte(ob#)
    FUNCTION fussballspieler_sturm(ob#)

Polizei und Geheimhaltung