Kurs:Programmieren in Aleph/Kontakt mit Java

Aus Wikiversity

Kontakt mit Java[Bearbeiten]

Aleph ist auch eine Erweiterung von Java. Im krassen Gegensatz zu Aleph ist Java eine äußerst umfangreiche Sprache mit strenger Syntax und Typisierung. Um eine sanften Einstieg in das Zusammenspiel dieser beiden Gegensätze zu ermöglichen steht ein kurzes Java-Programm namens "xyz.java" für erste Übungen bereit.

Das Java-Programm (die Blockkommentare wurden enfernt)

public class xyz {
static public int Cvalue = -11;      // class-FIELD
public        int Ivalue = -99;   // instance-FIELD

 public void test() {                // void-METHOD
  System.out.println( "Funktioniert!");
 }

 public int add( int a, int b) {      // int METHOD
  return a+b;
 }
}

ist sehr einfach und übersichtlich. Kein Grund, die Verwendung in Aleph nicht detailliert zu besprechen. Am Anfang werden die notwendigen Schritte sehr kompliziert erscheinen. Nach kurzer Zeit wird jedoch klar, dass genau diese Schritte in jedem Java-Programm vorhanden sind.

Eine Klasse bereitstellen[Bearbeiten]

Klassen werden in Aleph über ihren Namen identifiziert. Das übersetzte Programm (xyz.class) befindet sich im Verzeichnis von Aleph. Damit ist es im aktuellen Suchpfad von Java und die einfache Angabe des Dateinamens ermöglicht die Identifikation.

"xyz" classify

Die Klasse "xyz" liegt als Objekt auf dem Stack. Ganz genau betrachtet ist jede Klasse auch ein Objekt. Unkenntnis der Java-Programmierung führt hier oft zu Irritationen, aber vielleicht hilft folgender Zusatz:

Das classify-Command stellt

  • ein Objekt der Klasse bereit,
  • nicht eine Instanz der Klasse.

Auf jeden Fall steht die Klasse "xyz" jetzt auf dem Stack zur Verfügung.

Eine Instanz bereitstellen[Bearbeiten]

Die Klasse "xyz" hat keine spezielle Methode für die Instanziierung. Deshalb kann eine Instanz mit dem "default-Creator" erzeugt werden. Genau dieser wird hier angewendet.

"xyz"        //       --> name
classify     // name  --> class
instantiate  // class --> instance

Mit diesem Objekt von "xyz" werden nun ein paar "Versuche" angestellt. Zunächst werden die Methoden aufgerufen.

Methoden benutzen[Bearbeiten]

Die Methode "test" wird über ihren Namen identifiziert. Leider ist das nicht so einfach wie es sich anhört. Es kann durchaus mehrere Methoden geben, die vor ihrer Argumentliste gleiche Bezeichner haben, aber unterschiedliche Parameter. Deshalb verlangt Aleph auch die Einbeziehung der Arumentliste bei der Namensangabe. Für das erste Beispiel ist das noch einfach.

dup         // inst           --> inst inst
"test { }"  // inst inst      --> name inst inst
call        // name inst inst --> inst

Die Ausgabe im Protokoll-Fenster oder auf der Konsole liefert dann auch

Funktioniert!

Jetzt noch die zweite Methode "add". Sie verlangt Argumente und gibt ein Ergebnis zurück. Die Java-Typen der Argumente müssen jetzt für die komplette Namensgebung herangezogen werden.

3                  // inst           --> 3 inst
swap               // 3 inst         --> inst 3
4                  // inst 3         --> 4 inst 3
swap               // 4 inst 3       --> inst 4 3
"add { int int }"  // inst 4 3       --> name inst 4 3
call               // name inst 4 3  --> 7

Aleph behandelt also die Rückgaben von Java-Methoden wie Commands. Allerdings ist der hier gezeigte Aufruf von Methoden umständlich. Diese Vorgehensweise sollte nur angewendet werden, wenn es sich um einmalige Aufrufe von Methoden handelt. Das ist oft bei der Erstellung von Fenstern der Fall. Es ist vorteilhafter die Methoden genau wie Commands zu benutzen.

Methoden wie Commands einsetzen[Bearbeiten]

Es muss zunächst wieder der Weg durch die Instanzen beschritten werden. Also wieder klassifizieren und instanziieren

"xyz"        //       --> name
classify     // name  --> class
instantiate  // class --> inst

Dann die Methode der Java-Klasse identifizieren

"add { int int }"  // inst --> name inst

Jetzt liegen der Name der Methode und die Objektinstanz mit der benannten Methode auf dem Stack. Die Übernahme in den Sprachschatz von Aleph, also die Aufnahme der Methode als Command in das Dictionary, erfolgt mit

method plus  // name inst -->

Die Java-Methode "int inst.add( int a, int b)" ist jetzt als Command namens "plus" vorhanden. Ab jetzt genügt es

3 4 plus

anzugeben, um das vorherige Ergebnis zu erhalten. Zur besseren Übersicht und zum kopieren für eigene Experimente, noch einmal die ganze Prozedur als Quellcode


// *---------------------------------*
// * klassifizieren und instanziieren *
// *---------------------------------*

"xyz"              //           --> name
classify           // name      --> class
instantiate        // class     --> inst

// *----------------*
// * identifizieren *
// *----------------*

"add { int int }"  // inst      --> name inst

// *------------------------------*
// * als Command anwendbar machen *
// *------------------------------*

method plus        // name inst -->

3 4 plus
.S

Offenbar ist das Command "method" in seiner Arbeitsweise dem "Colon" ähnlich. Die nächste Zeichenfolge wird als Name verwendet. Die Abläufe in diesem Command sind aber nicht in Aleph formuliert, sondern in Java. Aleph braucht sich nur um das methodische Objekt zu kümmern. Genau das ist durch die Kombination aus dem Namen der Java-Methode und der Objektinstanz gegeben.

Aufgabe:
  1. Für die Methode "void test()" aus der Klasse "xyz" ein Aleph-Command mit der Bezeichnung "test" aufbauen und ausprobieren.
  2. Warum liegt der Ausgabestring des Commands "test" nach dem Aufruf nicht auf dem Stack?

Java-Variablen benutzen[Bearbeiten]

In der Nomenklatura von Java werden Variablen allgemeiner als "fields" bezeichnet. Nicht einmal im Ansatz haben "fields" etwas mit Arrays zu tun, die oft immer noch als "Feldvariablen" bezeichnet werden. Fields sind auch hier die Bezeichnung für Variablen im reinen Java-Kontext.

Eigentlich müssten Fields ähnlich zu behandeln sein wie Methoden. Auch hier gibt es die Möglichkeit über den Namen zuzugreifen, oder ein entsprechendes Command zu kreieren. Zunächst der "umständliche" Weg

Auslesen und speichern[Bearbeiten]

Es wird der gleiche Weg beschritten, wie bereits bei den Methoden. Ein Unterschied besteht nun darin, den in dem Field gespeicherten Wert auszulesen statt eine Methode aufzurufen.

"xyz" classify instantiate  // instance
"Ivalue"                    // name instance
swap                        // instance name
fetch                       // -99

Vorsicht! Ein Unterschied ist doch vorhanden. Die Reihenfolge der Stackelemente vor dem "fetch"-Command ist anders als beim "call"-Command.

Für das Speichern in einer Java-Variablen existiert das "store"-Command. Damit das Beispiel übersichtlich bleibt, wird zusätzlich eine Aleph-Variable eingesetzt.

"object" variable
"xyz" classify instantiate
"object" is
1234
"Ivalue" object store  // 1234  nach Ivalue speichern
"Ivalue" object fetch  // Inhalt von Ivalue kontrollieren.

Die Aleph-Variable "object" ist die Instanz von "xyz". Kurze Erinnerungsphase – Aleph-Variablen sind etwas, sie enthalten nichts.

Dieses Vorgehen über eine Variable mit der Instanz des Objekts funktioniert natürlich auch bei Methoden. Die Schreibweise ist übersichtlicher als den Stack zu manipulieren. Hier liegt ein klassisches Beispiel für die Verwendung von Variablen vor.

Java-Variablen als Aleph-Objekt einsetzen[Bearbeiten]

Aleph-Objekte sind Commands und damit funktional. Variablen, ob Java oder Aleph, sind ebenfalls funktional, denn sie übergeben etwas nachdem ihr Name aufgerufen wurde. Genau dieses Verhalten ist auch bei den Fields (Java-Variablen) vorhanden.

Das Field muss im Dictionary eingetragen werden. Die Vorgehensweise ist wie beim Command "method", nur dass jetzt das Command "field" benutzt wird. Im folgenden Beispiel trägt das Command den Namen "Field" (Großschreibung beachten).

"xyz" classify instantiate
"Ivalue" field Field

Die einfache Nennung des Namens "Field" sollte dann den Wert der Java-Variablen namens "Ivalue" auf dem Stack ablegen.

"xyz" classify instantiate  //      --> inst
"Ivalue" field Field        // inst -->
Field                       // -99

Aleph-Variablen erhalten ihre Zuweisungen über das Command "is". Für Fields muss es natürlich ein anderes sein. In Anlehnung an die Schreibweise in Java, wird das Command zum Speichern "set" genannt.

"xyz" classify instantiate  //      --> inst
"Ivalue" field Field        // inst -->
123 "Field" set
Field .

Zum Abschluss und um einen häufigen Fehler vorzubeugen, noch eine Sequenz mit "unerwartetem" Verhalten

"object-1" variable
"xyz" classify                 //       --> class
instantiate "object-1" is      // class -->

"object-2" variable
"xyz" classify                 //       --> class
instantiate "object-2" is      // class -->

"Cvalue" object-1 fetch
"Ivalue" object-1 fetch
- . newline .                  // Ergebnis lautet 88

"Cvalue" object-2 fetch
"Ivalue" object-2 fetch
- . newline .                  // Ergebnis lautet 88

-1234 "Cvalue" object-2 store  // Objekte beachten !!!!!
"Cvalue" object-1 fetch
"Ivalue" object-1 fetch
- .                            // Ergebnis lautet -1135

Die dritte Subtraktion ergibt stets das Ergebnis -1135, unabhängig von der Wahl der Objekte oder deren Kombination. Die "umständliche" Schreibweise wurde gewählt, damit die Abläufe detailliert untersucht werden können. Auch der Einsatz von "field"-Commands ändert nichts am Ergebnis. Für Java-Kundige eigentlich schnell zu durchschauen, für Unkundige praktisch nicht zu verstehen.

Aufgabe:

Nur für Java-Kundige.

Erläutern des Ergebnisses.

Die ersten Kontakte zwischen Aleph und Java sind geknüpft. Prinzipiell kann bereits jetzt auf jedes Java-Objekt zugegriffen werden.

Instanziierung mit Methode[Bearbeiten]

Es gibt Java-Klassen die zur Instanziierung spezielle Methoden verlangen – kurz: einen eigenen Creator benutzen. Das einfache default-Command "instantiate" funktioniert hier nicht. Die Tatsache, dass es auch noch beliebig viele dieser Creatoren geben kann, macht die Aufgabe nicht einfacher. Ein Beispiel macht das Problem offensichtlich und zeigt auch gleich die Vorgehensweise.

Ein Fenster der Klasse "JFrame" soll mit Titel instanziiert werden. Aus den möglichen Creatoren wird der für ein tituliertes Objekt gewählt.

"frame" variable

"Aleph-Fenster"       //                  --> title
"javax.swing.JFrame"  // title            --> name title
classify              // name title       --> class title
"{String}"            // class title      --> args class title
creator               // args class title --> creator
build                 // creator          --> inst

"frame" is

Creator-Methoden sind an sich namenlos. In Java werden sie mit "new Klassenname(...)" gestartet. In Aleph muss die Klasse auf dem Stack liegen. Dann wird die aus den "normalen" Methoden bekannte Argumentliste als String auf den Stack gelegt. Das "creator"-Commad erzeugt nun aus der Kombination von Klasse und Argumentliste die entsprechende Creator-Methode als Objekt. Es ist noch keine Instanziierung erfolgt. Erst das Command "build" erzeugt die Instanz.

Im Beispiel wird diese "JFrame"-Instanz an die Variable "frame" übergeben. Damit wird das (unvermeidliche) Ausprobieren sehr erleichtert.

250 100 frame "setSize{ int int}"      call
true    frame "setVisible { boolean }" call
Aufgabe:
  1. Welcher Unterschied besteht zwischen einer Zuweisung an eine Aleph-Variable und der an ein Field?
  2. Wie wird auf den Inhalt eines als Command existierenden Fields zugegriffen?
  3. Welche Objekte müssen für ein store-Command auf dem Stack liegen?

Zusammenfassung[Bearbeiten]

Aleph ermöglicht Zugriff auf alle zugänglichen Java-Objekte und deren Interna. Es kamen viele neue Comands hinzu, die Einträge im Dictionary vornehmen. Damit hier der Überblick erhalten bleibt, werden diese Commands als kreativ bezeichnet. Es handelt sich um:

  • : (colon)
Dieses Command ist nicht Bestandteil des Kernels.
  • method
Ist vergleichbar mit dem ":"-Command. Der Name wird aus dem Eingabestrom entnommen.
  • variable
Erzeugt eine Variable mit dem Namen dessen Zeichenkette auf dem Stack liegt.
  • field
Ist vergleichbar mit dem "variable"-Command. Commands dieser Art sind auf die vereinbarten Java-Typen beschränkt.

Abgesehen von "method" und dem ":" (colon) werden die Einträge für das Dictionary vom Stack übernommen. Es ist unverständlich, warum ausgerechnet "method" hier eine Ausnahme macht. Hoffentlich wird diese Ungereimtheit bald beseitigt.