Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...

Full Transcript

Objektorientierte Softwareentwicklung Objektorientierte Softwareentwicklung Sven Eric Panitz Hochschule RheinMain Version 1583 Generiert von LectureNotes Teaching System 30. Okt...

Objektorientierte Softwareentwicklung Objektorientierte Softwareentwicklung Sven Eric Panitz Hochschule RheinMain Version 1583 Generiert von LectureNotes Teaching System 30. Oktober 2019 Dieses Skript hat eine lange Tradition. Es basiert in Teilen auf den Skripten, die seit 2002 für unterschiedliche Vorlesungen im Bereich der Softwareentwick- lung entstanden sind. Seit 2002 hat sich viel in Java getan: es kamen Generics, Aufzählungstypen und For-Each-Schleifen in Java 5, Lambdas und Streams in Java 8, Typinferenz für lokale Variablen und die jshell in Java 10 hin zu und aktuell ab Java 12 geht es um die Ausweitung der switch-Anweisung zu einem vollen Pattern-Matching. Ich bemühe mich stets auf diese neuen Eigenschaften einzugehen und ein aktuelles Begleitskript zu meiner Vorlesung vorzulegen. Es ist zusammen mit den Aufgaben und Lernkarteikarten auf meiner Lernplattform subato.org zu verwenden. Zwischenzeitig hatte mein Skript über 500 Seiten und sollte möglichst viel Details in Java abbilden, mittlerweile habe ich mich entschieden, es wieder auf wesentliche Inhalte einzudampfen. Ein komplettes Java-Kompendium und Nachschlagwerk findet man in Standardbüchern. Dieses Skript ist kein Buch sondern begleitet die Vorlesung zu meinem Modul und ist im Kontext mit den bereit gestellten e-learning Inhalten und der Vorlesung zu studieren. Es ist auch nicht mit der gleichen Sorgfalt wie ein Buch geschrieben. Eine Reihe von wichtigen Java-Themen werden auch erst im getrennten Skript des Moduls »Programmiermethoden und Techniken« des zweiten Semesters behandelt. Besondere Dank gilt Kim Hoitz, die das Skript sowohl sprachlich als auch inhaltlich kommentiert hat. Ich danke dem Tutoring Team insbesondere Herrn Jens Möhrstedt, der es ermöglicht hat, das Skript auch in Papierform zur Verfügung zu stellen. Herrn Sebastian Pedersen gebührt Dank für die Gestaltung des Umschlags. Impressum ©2019 Sven Eric Panitz Umschlaggestaltung: Sebastian Pedersen Inhaltsverzeichnis 1 Einführung in die Welt der Softwareentwicklung 4 1.1 Aspekte der Softwareentwicklung....................... 4 1.2 Programmiersprachen............................. 10 1.3 Arbeiten mit der Kommandozeile....................... 12 1.3.1 Basisbefehle............................... 13 1.3.2 Nützliche Standardprogramme.................... 21 1.3.3 Erste Java Programme auf der Kommandozeile........... 25 1.4 Interaktives Java mit der jshell........................ 30 1.4.1 Ausdrücke auf Zahlen......................... 31 1.4.2 Arbeiten mit Variablen......................... 33 1.4.3 Vergleiche und Wahrheitswerte.................... 34 1.4.4 Ausdrücke für Zeichenketten...................... 35 1.4.5 Funktionen............................... 37 2 Grundkonzepte der Objektorientierung 40 2.1 Interaktive Entwicklung von Klassen..................... 40 2.2 Objektorientierte Modellierung........................ 43 2.3 Klassen und Objekte.............................. 46 2.3.1 Felder.................................. 47 2.3.2 Objekte................................. 48 2.3.3 Objekte der Klasse String...................... 51 2.3.4 Methoden................................ 52 2.4 Der Bezeichner this.............................. 54 2.5 Statische Eigenschaften einer Klasse..................... 55 2.5.1 Statische Methoden.......................... 55 2.5.2 Statische Felder............................. 56 3 Imperative und funktionale Konzepte 58 3.1 Primitive Typen................................ 58 3.1.1 Zahlenmengen in der Mathematik................... 59 3.1.2 Zahlenmengen im Rechner....................... 59 3.1.3 Zeichen und Buchstaben........................ 62 3.1.4 Boxen für primitive Typen....................... 65 3.2 Ausdrücke.................................... 66 3.2.1 Arithmetische Operatoren....................... 66 3.2.2 Vergleichsoperatoren.......................... 67 3.2.3 Logische Operatoren.......................... 68 1 3.2.4 Der Bedingungsoperator........................ 69 3.3 Anweisungen.................................. 70 3.3.1 Zuweisungen.............................. 70 3.3.2 Fallunterscheidungen.......................... 72 3.3.3 Iteration................................. 77 3.4 Rekursion.................................... 87 3.4.1 Rekursion und Schleifen........................ 90 3.4.2 Einsatz von Rekursion......................... 92 3.5 Reihungen (Arrays)............................... 93 3.5.1 Deklaration von Reihungen...................... 93 3.5.2 Erzeugen von Reihungen........................ 93 3.5.3 Zugriff auf Elemente.......................... 94 3.5.4 Ändern von Elementen......................... 95 3.5.5 Die für-alle-Schleife........................... 95 4 Weiterführende Konzepte der Objektorientierung 97 4.1 Vererbung.................................... 97 4.1.1 Hinzufügen neuer Eigenschaften.................... 99 4.1.2 Überschreiben bestehender Eigenschaften.............. 99 4.1.3 Konstruktion.............................. 100 4.1.4 Zuweisungskompatibilität....................... 101 4.1.5 Späte Bindung (late binding)..................... 103 4.1.6 Zugriff auf Methoden der Oberklasse................. 108 4.1.7 Die Klasse Object........................... 108 4.2 Pakete...................................... 114 4.2.1 Paketdeklaration............................ 114 4.2.2 Übersetzen von Paketen........................ 115 4.2.3 Starten von Klassen in Paketen.................... 116 4.2.4 Das Java Standardpaket........................ 116 4.2.5 Benutzung von Klassen in anderen Paketen............. 117 4.2.6 Importieren von Paketen und Klassen................ 117 4.2.7 Statische Imports............................ 119 4.2.8 Sichtbarkeitsattribute......................... 120 4.3 Schnittstellen (Interfaces) und abstrakte Klassen.............. 125 4.3.1 Schnittstellen.............................. 125 4.3.2 Abstrakte Klassen........................... 133 5 Graphische Benutzeroberflächen mit Swing 134 5.1 Swings GUI-Komponenten........................... 135 5.1.1 Top-Level Komponenten........................ 135 5.1.2 Zwischenkomponenten......................... 136 5.1.3 Atomare Komponenten........................ 137 5.2 Gruppierungen................................. 138 5.2.1 Flow Layout.............................. 139 2 5.2.2 Border Layout............................. 140 5.2.3 Grid Layout............................... 141 5.3 Eigene GUI-Komponenten........................... 142 5.3.1 Fraktale................................. 144 5.4 Reaktion auf Ereignisse............................ 148 5.4.1 Der ActionListener.......................... 149 5.4.2 Innere und Anonyme Klassen..................... 151 5.4.3 Lambda Ausdrücke........................... 153 5.4.4 Mausereignisse............................. 154 5.4.5 Fensterereignisse............................ 156 5.5 Zeitgesteuerte Ereignisse............................ 157 5.5.1 Animationen.............................. 159 5.6 Weitere Swing Komponenten......................... 162 6 Weiterführende Konzepte 166 6.1 Aufzählungstypen................................ 166 6.2 Variable Parameteranzahl........................... 168 6.3 Generische Typen................................ 169 6.3.1 Generische Klassen........................... 170 6.3.2 Vererbung................................ 173 6.3.3 Generische Schnittstellen....................... 176 6.3.4 Generische Methoden......................... 179 6.3.5 Beispiel einer eigenen Listenklasse.................. 180 6.3.6 Standard Sammlungsklassen...................... 183 6.4 Ein- und Ausgabe................................ 192 6.4.1 Dateibasierte Ein-/Ausgabe...................... 193 6.4.2 Textcodierungen............................ 195 6.4.3 Gepufferte Ströme........................... 198 6.4.4 Lesen von einem Webserver...................... 199 6.4.5 Ströme für Objekte........................... 200 6.5 Ausnahmen................................... 202 6.5.1 Ausnahme- und Fehlerklassen..................... 202 6.5.2 Werfen von Ausnahmen........................ 203 6.5.3 Deklaration von geworfenen Ausnahmen............... 206 6.5.4 Eigene Ausnahmeklassen........................ 208 6.5.5 Fangen von Ausnahmen........................ 209 6.5.6 Der Aufrufkeller............................ 215 6.5.7 Schließlich und finally......................... 217 6.5.8 Anwendungslogik per Ausnahmen................... 218 7 Zusammenfassung und Ausblick 220 7.1 Fragen und Antworten............................. 220 3 1 Einführung in die Welt der Softwareentwicklung Sie haben sich für das Studium eines Informatikstudienganges entschieden und werden damit u.a. in den verschiedenen Modulen verschiedene Aspekte zur Entwicklung von Software kennenlernen. Dieses wird eines der zentralen Inhalte des Studiums sein, für das in diesem Modul die Grundlagen gelegt werden. 1.1 Aspekte der Softwareentwicklung Ich schreibe. Ich bin Software-Autor. [...] Ich schreibe ab jetzt nur noch Software, die was mit meinem Leben zu tun hat. Autobiogra- phisch. Kristof Magnusson: Männerhort Das obige Zitat aus der Komödie »Männerhort« ist näher an der Realität, als man denken mag; denn im Prinzip ist Software nichts weiter als ein Text, den ein oder mehrere Autoren geschrieben haben. Insofern ist es durchaus legitim bei Programmierern von Autoren zu sprechen. Und je mehr sich die Autoren mit ihrer Software identifizieren, desto besser ist meistens auch die Qualität der Software. Dieses gilt oftmals besonders für quelltextoffene Software. Hier steht immerhin der gute Ruf der Autoren auf dem Spiel. Auf der einen Seite scheint die Entwicklung von Software einfach zu sein. Es ist ein Text zu schreiben. Hierzu wird eigentlich kein anderes Werkzeug als ein Texteditor be- nötigt. Andererseits ist die Entwicklung von Software ein sehr komplexer Vorgang, denn ein Softwaresystem ist oft sehr umfangreich und besteht aus vielen Einzelkomponenten. Um dieser Komplexität Herr zu werden, hat die Informatik über die letzten Jahrzehnte viele Techniken und Prozesse entworfen, die bei der Entwicklung von Software helfen sollen. Im Laufe eines Informatikstudiums werden Sie in verschiedenen Modulen die vie- len unterschiedlichen Aspekte der Software-Entwickung kennenlernen. In diesem Modul soll Ihnen hierzu ein Grundüberblick und ein erstes Fundament in der Programmierung gelegt werden. Die Fragestellungen der Softwareentwicklung reichen von technischen Aspekten, wie die Programmierung von Betriebsmitteln, bis hin zu Prozessen und Rollen beim Arbeiten im Team. Es ist zu klären, für welche Hardware was für Software mit welcher Funktionalität 4 auf welche Weise zu entwickeln ist. Wie kann die Qualität der Software sicher gestellt wer- den. Wie können die Kosten des Entwicklungsprozesses abgeschätzt werden. Wie gelangt die Software zum Kunden und kann sie im laufenden Betrieb gewartet werden. Wir geben eine ungeordnete und sicher nicht vollständige Liste verschiedenster Aspekte der Softwareentwicklung: Anforderungsanalyse: Am Anfang steht die banale Frage, für wen Software er- stellt werden soll und was diese Software ganz allgemein können muss. Was ist der Einsatzbereich. Wer sind die Anwender. Die Analyse dieser solcher Fragen wird Anforderungsanalyse genannt. Allein aus der Tatsache, dass wir im Wahlpflichtbe- reich ein eigenes Modul zu diesem Thema haben, zeigt, dass die Anforderungen oft nicht so offensichtlich sind, wie es scheint. Spezifikation: Für einzelne Komponenten und Funktionalitäten ist zu klären, was diese für ein genaues Eingabe- Ausgabeverhalten haben sollen. Diesen Schritt der Softwareentwicklung bezeichnet man allgemein als Spezifikation. Spezifiziert wird auf den unterschiedlichsten Abstraktionsebenen. Allgemein für die komplet- te Software, für einzelne Komponenten oder auch für kleinste Teileinheiten. Es gibt verschiedene formale und semi-formale Sprachen, zur Spezifikation. Im Ba- chelorstudiengang werden Sie die gängigsten Spezifikationssprachen in dem Modul »Softwaretechnik« kennen lernen. Weitere formale Spezifikationssprachen werden im Masterstudiengang im Modul »Formale Modelle« vorgestellt. Grundlage fast al- ler Spezifikationssprachen ist ein gewisses formales Handwerkszeug, das im Modul »Diskrete Strukturen« vermittelt wird. Sicherheit und Datenschutz: Wer die Tagespresse verfolgt, sieht, dass die Sicher- heit von Daten ein großes und ernstes Thema ist. Das Modul »IT-Security« wird hierzu in Ihren Studium die theoretischen Grundlagen dieses Aspektes vermitteln. Ergonomie und Benutzerfreundlichkeit Jeder Anwender hat sich sicher schon einmal darüber geärgert, dass Software nicht intuitiv oder folgerichtig zu bedie- nen war. Das einfache Dinge nur kompliziert und durch viele Schritte realisiert werden konnten oder auch, dass die Software die wichtigen Informationen nicht leicht zugänglich und übersichtlich dargestellt hat. Auch eine in der Funktionalität fehlerfreie Software kann unbrauchbar sein, weil sie zu schwer zu bedienen ist. Im Wahlbereich unseres Curriculums findet sich das Modul »Usability Engineering«, dass sich mit diesen Fragen auseinander setzt. Optimierung Ein wichtiger Aspekt einer Software ist, dass sie nicht nur korrekt funktioniert, sondern auch einen guten Durchsatz und schnelle Antwortzeiten hat. Hierbei kann eine schnelle Antwortzeit aber auch ganz Unterschiedliches bedeuten. Von einer Handelsplattform für Börsengeschäfte wird eine extrem schnelle Abar- beitung der Anfrage erwartet, ein System das ein dreidimensionalen Film rendered darf durchaus manchmal Stunden brauchen. Egal in welchem Gebiet die Software eingesetzt wird, sie soll möglichst effizient laufen. Hierbei wird es unter Umständen nötig, korrekt laufende Programme zu optimieren. Optimierungen können den ver- wendeten Algorithmus betreffen, der in einer hohen Komplexitätsklasse liegt und 5 durch einen effizienteren ersetzt werden kann. Es kann das Zwischenspeichern von Teilergebnissen beinhalten, so dass mehrfaches Errechnen gleicher Zwischenergeb- nisse entfällt. Es kann aber auch auf einer mikroskopischen Ebene passieren, indem besonders häufig benutze Programmteile schon in kleinsten Teilen auf Assembler- ebene optimiert werden. Mit der Komplexität bestimmter Algorithmen beschäftigt sich in unserem Curriculum unter anderem das Modul »Algorithmen und Daten- strukturen«. Tests Beim Theater sagt man: »Alles, was nicht geprobt ist, geht schief.« Ähnliches gilt für Software. Alles, was nicht getestet wurde, hat eine hohe Wahrscheinlichkeit, dass es nicht funktioniert. Doch wie testet man Software am besten? Reicht es ein paar Anwender das Programm ausprobieren zu lassen? Welche Komponenten las- sen sich automatisch reproduzierbar testen? Welche Granularität können die Tests haben? Wird in Kenntnis des Quellcodes getestet oder ohne diese Kenntnis das Ein-/Ausgabeverhalten der Software? Und wer testet? Die Entwickler selbst, oder Personen, die die Software nicht entwickelt haben? In diesem Modul werden wir erste Testszenarien für Entwicklertests kennenlernen. Ein umfassender Überblick wird in dem Modul »Softwaretechnik« gegeben. Logging Besonders für Server-Anwendungen, die über einen langen Zeitraum lau- fen, ist es wichtig, dass ein Administrator nachverfolgen kann, was über einen be- stimmten Zeitraum mit der Anwendung vorgefallen ist. Wie viele Anfragen bedient wurden, ob es Fehlerfälle gab oder auch wie gut der Durchsatz der Anwendung war. Hierzu ist es unerlässlich, dass eine Anwendung ein Logbuch führt, in dem alle wichtigen Schritte des Prorammablaufs dokumentiert sind. Dieses Logbuch ist ins- besondere wichtig, wenn es zu Fehlern kam, und die Fehlerursache ermittelt werden muss. Verifikation Klar, Software soll fehlerfrei laufen. Aber nicht immer genügen Tests, um das fehlerfreie Verhalten eines Programms zu zeigen. Tests können immer nur endlich viele Eingaben eines Programms checken. Ein Programm hat aber poten- tiell unendlich viele Zustände und Eingaben. Mit formalen Verifikationsmethoden versucht man für besonders kritische Software, die vielleicht eine gefährliche Anlage steuert, mathematisch zu beweisen, dass sie für alle Eingaben immer das gewünsch- te Verhalten zeigt. Man unterscheidet: – partielle Korrektheit: wenn das Programm für eine bestimmte Eingabe ein Ergebnis liefert, dann ist dieses bezüglich der Spezifikation korrekt. – totale Korrektheit: Das Programm ist partiell korrekt und terminiert für jede Eingabe, d.h. liefert immer nach endlich langer Zeit ein Ergebnis. Internationalisierung Die Welt ist insbesondere durch die Daten-Kommunika- tionsnetze enger zusammen gerückt. Ein Stück Software wird nicht für ein Land oder einen Kulturkreis allein geschrieben, sondern wird potentiell weltweit einge- setzt. Unter der Internationalisierung (abgekürzt als I18N für internationalization, der Buchstabe I 18 weitere Buchstaben und schließlich der Buchstabe N) versteht 6 man, dass die Software in verschiedenen Kulturkreises eingesetzt werden kann. Die- ses beinhaltet z.B. dass alle Schriftzeichen in einer Textverarbeitung benutzt werden können oder dass die Schreibrichtung in einem Texteingabefeld eingestellt werden kann, da in einigen Schriften von rechts nach links in anderen von links nach rechts, und teilweise auch von oben nach unten geschrieben wird. Lokalisierung Die Lokalisierung beschäftigt sich auch mit der globalen Einsetz- barkeit der Software. Hier geht es zusätzlich darum, dass die Benutzerführung in verschiedenen Sprachen vorliegt, zum Beispiel die Menübeschriftungen in mehreren Sprachen vorliegen und die Hilfetexte übersetzt worden sind. Entsprechend I18N wird Lokalisierung auch als L12N abgekürzt. Kurz gefasst kann man sagen: in einer internationalisierten Software lassen sich auch chinesische Texte schreiben, aber die Knöpfe und Menüs sind weiterhin auf englisch beschriftet. In einer lokalisierten Software gibt es auch Beschriftungen, Hilfetexte etc auf chinesisch. Vorgehensmodell Wie schreibt man eine Software. Einfach los tippen, bis man fertig ist, wäre ein Vorgehensmodell. Ein Vorgehensmodell legt fest, in welchen Schritten, mit welchen Zwischenergebnissen eine Software im Team erstellt wird. Dabei kann das Team auch aus einer Person bestehen, wie es in der Regel bei einer Bachelorarbeit der Fall ist. Es wurden in der Informatik eine Reihe unterschiedli- cher Vorgehensmodelle entwickelt. Auf theoretischer Ebene werden diese Ihnen im Modul »Softwaretechnik« vorgestellt. Praktisch werden Sie spätestens im Wahlpro- jekt des fünften Semesters nach einem Vorgehensmodell arbeiten. Dokumentation Schön wäre es, wenn der Quelltext einer Software selbsterklärend wäre. Manche Programmierer sind auch der Ansicht: »The code is documentation enough.«. Dieses ist leider selten der Fall, auch wenn es auch eine Bestrebung in der Entwicklung neuer Programmiersprachen ist, dass Programme verständlicher und selbsterklärender sind. Daher ist es unumgänglich, dass zu einer Software eine Dokumentation existiert. Wobei man drei Adressaten der Dokumentation identifi- zieren kann: – Endanwender: für die Endanwender wird ein Benutzerhandbuch geschrie- ben. Hier sind keinerlei Interna der Software beschrieben, sondern lediglich die Funktionalität der Benutzerschnittstelle. – Entwickler die Komponenten benutzen: die meiste Software ist nicht monolithisch, sondern besteht aus einzelnen Komponenten, die in unterschied- lichen Softwareprojekten wiederverwendet werden können. Für diese Kompo- nenten ist die Programmierschnittstelle, das sogenannte API (application pro- grammers interface) zu beschreiben. Es ist zu dokumentieren, welche Funk- tionalität die Komponente anbietet und wie diese von einem Programmierer zu benutzen ist. Welche Vorbedingungen gelten müssen und welche Nachbe- dingungen nach Aufruf einer Schnittstelle gelten. Interna der Umsetzung sind hierbei nicht dokumentiert. – Entwickler der Software selbst: Sie werden schon in Kürze feststellen, dass Sie Ihre eigenen Programme schon nach wenigen Wochen manchmal gar Tagen 7 nicht mehr verstehen. Sie werden sich fragen: was habe ich mir da nur gedacht? Deshalb ist es sinnvoll, seinen Programmtext zu kommentieren. Innerhalb des Programmtextes sind Kommentarzeilen eingefügt, die erklären, wie ein be- stimmter Teil des Codes funktioniert. Diese Kommentare sollen helfen, dass die Kollegen im Team oder man selbst, oder Kollegen, die irgendwann in der Zukunft die Software weiterentwickeln, den Programmtext besser verstehen. In vielen Firmen wird verlangt, dass das API auf Englisch zu dokumentieren und auch dass Kommentare im Programmtext auf Englisch zu schreiben sind. Dieses soll erleichtern, dass auch internationale Kollegen mit ins Team aufgenommen werden können oder die Software ins Ausland zur Weiterentwicklung verkauft werden kann. Auch bei einer kleinen Firma, die in Deutschland angesiedelt ist und nur deutsche Mitarbeiter hat, weiß man nie, was die Zukunft bringt. Vielleicht wird die Firma von einer anderen in Korea angesiedelten Firma aufgekauft, vielleicht wird es eine lose Zusammenarbeit mit einer französischen Firma geben. Auf jeden Fall sind solche Schritte weniger verbaut, wenn der Programmtext auf Englisch dokumentiert und kommentiert ist. Es empfiehlt sich also, sich frühzeitig anzugewöhnen, seinen Quelltext in seinem rudimentären Englisch zu dokumentieren. Wartung Wenn Sie in Ihrem betriebspraktischen Modul in einer Firma sind, die Software entwickelt, werden sie vielleicht feststellen, dass dort mehr Zeit damit ver- bracht wird, bestehende Software zu warten als neue Software zu schreiben. Zur Wartung gehört zunächst einmal, dass Fehler, die erst im Betrieb beim Kunden gefunden wurden, korrigiert werden. Es kann sich dabei um echte funktionale Fehl- funktionen, die bis zum Programmabsturz führen können, handeln aber auch um Probleme der Benutzerfreundlichkeit und der Ausführungsgeschwindigkeit. Einen großen Wartungsaufwand fordern oft neue Versionen des Systems, auf dem die Software installiert ist. Sei es das Betriebssystem, ein Webserver oder auch die Datenbank. Portieren: Oft wird es nötig, ein Programm auf eine andere Plattform zu portie- ren. Ein unter Windows erstelltes Programm soll z.B. auch auf Unix-Systemen zur Verfügung stehen. Einsatz eines Debuggers Bei einem Programm ist immer damit zu rechnen, dass es Fehler enthält. Diese Fehler werden im besten Fall von der Qualitätssi- cherung entdeckt, im schlechteren Fall treten sie beim Kunden auf. Um Fehler im Programmtext zu finden, gibt es Werkzeuge, die ein schrittweises Ausführen des Programms ermöglichen (debugger). Dabei lassen sich die Werte, die in bestimmten Speicherzellen stehen, auslesen und auf diese Weise Fehler finden. Architektur Eine Software besteht aus vielen Einzelkomponenten, die unterschied- liche Teilaufgaben übernehmen und im besten Fall für verschiedene Softwarepro- jekte wiederverwendbar sind. Die Aufteilung der Software in einzelne Komponenten wird als Architektur bezeichnet. Es gibt bestimmte Standardarchitekturmuster, die bei ähnlichen Aufgabenstellungen Anwendung finden können. Elementare Program- miermuster werden im Modul »Softwaretechnik« vorgestellt. 8 Kommunikation Es gibt heute kaum noch Software, die nicht auf irgendeine Art und Weise über ein Netzwerk kommuniziert. Insofern ist ein wichtiger Aspekt der Softwareentwicklung, wie diese Kommunikation gemacht wird. Insbesondere auch wie eine sichere Kommunikation erreicht wird und wie sich die Software bei Ausfall der Kommunikationswege verhalten soll. Die Grundlagen zur Datenkommunika- tion werden im Modul »Rechnernetze und Telekommunikation« vermittelt. Mit Anwendungen, die stark auf dem Internet basieren, beschäftigt sich das Modul »Webbasierte Anwendungen«. Datenhaltung Kaum ein Softwareprojekt kommt ohne eine Komponente zur Spei- cherung umfangreicher Daten aus. Man spricht dabei von Persistenz. Daten blei- ben erhalten, auch wenn das Programm nicht mehr läuft. Eine einfache Form der Datenpersistenz ist eine Datei, in der die Daten in irgendeiner Form geschrieben werden. In der Regel haben Daten eine Struktur und werden in einer strukturier- ten Form abgespeichert, um in dieser Struktur effizient suchen zu können. Hierzu gibt es Datenbanken. Bereits im zweitem Semester werden Sie im entsprechendem Modul die Grundlagen der Datenbanktechnologie zur Softwareentwicklung kennen lernen. Algorithmen In der Regel erhalten Unterprogramme bestimmte Eingaben, für die eine Ausgabe zu berechnen ist. Der Weg aus den Einzelschritten, wie diese Ausgabe erzeugt wird, wird als Algorithmus bezeichnet. Für viele typische immer wieder benötigte Aufgaben, wie zum Beispiel dem Sortieren einer Liste von Daten, gibt es Standardalgorithmen, auf die in der Software-Entwicklung zurück gegriffen werden kann. Im zweiten Semester im Modul »Algorithmen und Datenstrukturen« werden die elementarsten Standardalgorithmen vermittelt, sowie grundlegende Gedanken über die Komplexität bestimmter Algorithmen. Codierung Die eigentliche Codierung ist in der Regel der einzige Schritt, der direkt Code in der gewünschten Programmiersprache von Hand erzeugt. Alle anderen Schritte der Programmierung sind mehr oder weniger unabhängig von der zugrunde liegenden Programmiersprache. Für die Codierung empfiehlt es sich, Konventionen zu verabreden, wie der Co- de geschrieben wird, was für Bezeichner benutzt werden, in welcher Weise der Programmtext eingerückt wird. Entwicklungsabteilungen haben zumeist schriftlich verbindlich festgeschriebene Richtlinien für den Programmierstil. Dieses erleichtert, den Code der Kollegen im Projekt schnell zu verstehen. Refaktorisierung Man sagt zwar gerne »Never change a running system.« oder auch »If it works, do not fix it«, doch können wir das in der Software-Entwicklung so nicht stehen lassen. Funktionierende Lösungen können unnötig komplex und unübersichtlich sein, so dass sie auf lange Sicht schwer zu warten sind und auch nicht leicht um weitere Funktionalität erweitert werden kann. Hier ist es oft sinnvoll, den Code zu refaktorieren, d.h. umzuschreiben, so dass er durch eine einfachere und übersichtlichere Lösung ersetzt werden kann. Dieses kann man nur sicher machen, wenn es eine ausreichende Testabdeckung gibt, so dass man zeigen kann, dass die 9 neue Lösung sich ebenso wie die alte verhält. Oft ist die Refaktorierung das Resultat eines Reviews zum Beispiel in Form eines code walk-through bei dem der Entwickler seinen Programmtext zeilenweise zusammen mit anderen Entwicklern durchgeht. Wie Sie sehen, gibt es einiges zu lernen in Ihrem Studium. Auf jeden Fall wird Ihnen nicht langweilig werden. Beginnen wir also mit den ersten Schritten zur Ausbildung zum Software-Autor. 1.2 Programmiersprachen Auch wenn der letzte Abschnitt gezeigt hat, dass die eigentliche Codierung der Software nur ein kleiner Teil des Projektes ausmacht, sind doch eine oder mehrere Programmier- sprachen auszuwählen, in denen das Projekt realisiert wird. Es gibt mittlerweile mehr Programmiersprachen als natürliche Sprachen.1 Die meisten Sprachen führen entsprechend nur ein Schattendasein und die Mehrzahl der Programme konzentriert sich auf einige wenige Sprachen. Programmiersprachen lassen sich nach den unterschiedlichsten Kriterien klassifizieren. Im folgenden eine hilfreiche Klassifizierung in fünf verschiedene Hauptklassen. imperativ (C, Pascal, Fortran, Cobol): das Hauptkonstrukt dieser Sprachen sind Befehle, die den Speicher manipulieren. objektorientiert (Java, C++, C#, Objective C, Eiffel, Smalltalk): Daten werden in Form von Objekten organisiert. Diese Objekte bündeln mit den Daten auch die auf diesen Daten anwendbaren Methoden. funktional (Scala, Lisp, ML, Haskell, Scheme, Erlang, Clean, F#): Programme werden als mathematische Funktionen verstanden und auch Funktionen können Daten sein. Dieses Programmierparadigma versucht, sich möglichst weit von der Architektur des Computers zu lösen. Veränderbare Speicherzellen gibt es in rein funktionalen Sprachen nicht und erst recht keine Zuweisungsbefehle. Skriptsprachen (Javascript, Perl, AWK): solche Sprachen sind dazu entworfen, einfache kleine Programme schnell zu erzeugen. Sie haben meist kein statisches Typsystem und nur eine begrenzte Zahl an Strukturierungsmöglichkeiten, oft aber eine mächtige Bibliothek, um Zeichenketten zu manipulieren oder sehr einfache und intuitive Anweisungen, die es ermöglichen schnell eine lauffähige Lösung zu programmieren. logisch (Prolog): aus der KI (künstlichen Intelligenz) stammen logische Program- miersprachen. Hier wird ein Programm als logische Formel, für die ein Beweis ge- sucht wird, verstanden. 1 Wer Interesse hat, kann im Netz einmal suchen, ob er eine Liste von Programmiersprachen findet. 10 Viele moderne Programmiersprachen versuchen die besten Konzepte aus all diesen Welten zu kombinieren. Ein typischer Vertreter für eine Sprache, die das funktionale und das objektorientierte Paradigma vereint ist Scala. Eine weitere Unterscheidung von Programmiersprachen kann in der Art des Ausführungs- modells getroffen werden. Der Programmierer schreibt den lesbaren Quelltext seines Pro- gramms. Um ein Programm auf einem Computer laufen zu lassen, muss es erst in einen Programmcode übersetzt werden, den der Computer versteht. Für diesen Schritt gibt es auch unterschiedliche Modelle: kompiliert (C, C++, Cobol, Fortran): in einem Übersetzungsschritt wird aus dem Quelltext direkt das ausführbare Programm erzeugt, das dann unabhängig von irgendwelchen Hilfen der Programmiersprache ausgeführt werden kann. interpretiert (Lisp, Scheme, Javascript): der Programmtext wird nicht in eine ausführbare Datei übersetzt, sondern durch einen Interpreter Stück für Stück an- hand des Quelltextes ausgeführt. Hierzu muss stets der Interpreter zur Verfügung stehen, um das Programm auszuführen. Interpretierte Programme sind langsamer in der Ausführung als übersetzte Programme. abstrakte Maschine über byte code (Java, Scala, Kotlin, ML): dieses ist qua- si eine Mischform aus den obigen zwei Ausführungsmodellen. Der Quelltext wird übersetzt in Befehle nicht für einen konkreten Computer, sondern für eine abstrakte Maschine. Für diese abstrakte Maschine steht dann ein Interpreter zur Verfügung. Der Vorteil ist, dass durch die zusätzliche Abstraktionsebene der Übersetzer un- abhängig von einer konkreten Maschine Code erzeugen kann und das Programm auf auf allen Systemen laufen kann, für die es einen Interpreter der abstrakten Maschine gibt. Wir benützen in diesem Modul die Programmiersprache Java aus mehreren pragmati- schen Gründen: Java ist objektorientiert und das objektorientierte Paradigma soll in diesem Mo- dul vermittelt werden (dieses spricht zum Beispiel gegen Sprachen wie C, Pascal, Haskell). Java ist im Vergleich zu manch anderer Sprache relativ aufgeräumt und die Anzahl der Konzepte noch recht übersichtlich, so dass Java didaktisch zum Unterrichten gut geeignet ist (dieses spricht zum Beispiel gegen Sprachen wie C++ oder Scala). Java wird in der Praxis viel eingesetzt und ist für alle gängigen Plattformen geeig- net. Dabei findet sich heutzutage Java nicht nur für Desktop und Server-Anwen- dungen sowohl auf Windows Betriebssystemen als auf Linux-Systemen, sondern auch für die Programmierung von Android Smartphones oder Webanwendungen mit Google Web Tool (dieses spricht zum Beispiel gegen Sprachen wie Objective C oder C#.) Man kann trefflich über die Vor- und Nachteile unterschiedlicherer Sprachen streiten, soll- te aber bei der Wahl der Programmiersprache stets pragmatisch sein und sich nicht zu 11 sehr auf emotionale Diskussionen einlassen. Streits über unterschiedliche Programmier- sprachen sind müßig. Jeder hat aus unterschiedlichen Gründen Favoriten, aber ein guter Informatiker sollte sich nach etwas Einarbeitung in jeder Sprache zurecht finden. Insbe- sondere sollte man sich bei der Wahl der Programmiersprache von dem Einsatzgebiet der Software leiten lassen.2 1.3 Arbeiten mit der Kommandozeile Wahrscheinlich ist das Hauptunterscheidungsmerkmal zwischen einem Endanwender und einem Informatiker, dass der Informatiker mit der Kommandozeile seines Betriebssystems umgehen kann. Seit Anfang der 80er Jahre gibt es graphische Benutzeroberflächen, die den Umgang mit dem Computer für Endanwender vereinfacht hat. Vorreiter war hier sicher zum einem die Firma Apple mit ihren Macintosh Rechnern aber auch andere Sys- teme stellten in den 80er Jahren intuitive graphische Benutzeroberflächen zur Verfügung, wie der Atari ST oder Commodore Amiga. Ebenso bekamen in dieser Zeit Unix Betriebs- systeme komfortable graphische Benutzeroberflächen wie Suns Solaris und HP-UX. Vor dieser Zeit war eine Benutzerinteraktion immer rein über die Tastatur und fast immer über eine Kommandozeile. Bis heute stellen alle Betriebssysteme einen direkten textuellen Zugang über eine Kommandozeile zur Verfügung. Eine Kommandozeile ist ein Programm, das Texteingaben erwartet und diese für bestimmte Aktionen im Betriebssys- tem ausführt. Hierzu gehört zum Beispiel, dass man über die Kommandozeile beliebige Programme starten kann. Auch Programme, die selbst wieder eine graphische Benutzer- oberfläche haben. Alle Programme können aber auch selbst textuelle Ausgaben auf die Kommandozeile schreiben und Texteingaben von der Kommandozeile lesen. Die Kommandozeile ist also in der Regel nicht die direkte Interaktion mit dem Betriebs- system, sondern selbst ein Programm, das die Benutzereingaben interpretiert und in Betriebssystembefehle umsetzt. Ein solches Terminalprogramm wird als shell bezeichnet. Wir werden im Folgenden einen rudimentären Umgang mit dem Programm bash zei- gen. bash steht für GNU Bourne-Again SHell. Für Linux steht die bash standardmäßig als Kommandozeilenprogramm zur Verfügung. Auf Windows-Systemen gibt es Software- Pakete, die installiert werden können, so dass genauso auf Windows mit bash gearbeitet werden kann, wie auf Linux, zum Beispiel mit http://www.cygwin.com/. Der Vorteil des Umgangs mit der Kommandozeile ist vielfältig. Es lassen sich hier vie- le Aufgaben unabhängig von anderen graphischen Programmen durch Eingabe weniger Befehle bewerkstelligen. Der Zugang zum Betriebssystem ist direkter. Dinge die einem graphische Programme nicht zeigen sondern verstecken, können eingesehen werden. Es lassen sich leicht Arbeitsschritte durch Skripte automatisieren, was bei graphischen Pro- grammen so nicht möglich ist. Und vor allen Dingen, selbst wenn keine graphische Be- nutzeroberfläche mehr vorliegt, lassen sich mit der Kommandozeile alle Funktionen des 2 Und wer es wissen will: für eigene kleine Projekte benutze ich persönlich Scala oder Haskell, für Webanwendungen GWT oder das Scala Lift Framework,und für mein Smartphone Java oder Kotlin für Android. 12 Systems kontrollieren. Besonders schnell erkennt man den Nutzen der Kommandozeilen, wenn man einen Server über das Internet administrieren muss. Ein Zugang zu einem Server steht über eine Kommandozeile immer zur Verfügung, eine graphische Benutzero- berfläche jedoch so gut wie nie. Also gibt es Gründe genug, den Umgang mit Kommandozeilenbefehlen einzuüben und diesen Umgang im Laufe des Studiums immer weiter zu verbessern. Zum Glück ist es gar nicht so schwer und die wichtigsten Befehle sind schnell erlernt. Das Modul »Einführung in die Informatik« bietet ausführlich Gelegenheit, den Umgang mit der Kommandozeile einzuüben. In Kontext unseres Moduls geben wir jetzt eine Schnelleinführung in die wichtigsten ersten Schritte, die zum Schreiben, Kompilieren und Ausführen von Java-Programmen notwendig sind. 1.3.1 Basisbefehle Wenn man die Kommandozeile geöffnet hat, befindet diese sich immer in einem Ordner des Dateisystems. Alle Befehle, die eingegeben werden beziehen sich auf diesem Ordner. Er wird auch als Arbeitsverzeichnis bezeichnet. ls Dateien Auflisten Der erste Befehl, den wir vorstellen, dient dazu die Dateien des Arbeitsverzeichnisses aufzulisten. Er besteht nur aus zwei Buchstaben: ls. ls wird als list gesprochen. Geben wir den Befehl in der Kommandozeile aus, so bekommen wir eine Auflistung aller Dateien des Arbeitsverzeichnisses. panitz@ThinkPad-T430:~/oose$ ls panitz@ThinkPad-T430:~/oose$ In diesem Fall war die Auflistung etwas enttäuschend, denn es befindet sich keine Datei im Arbeitsverzeichnis. Wird der Befehl in einem anderen Arbeitsverzeichnis aufgerufen, in dem sich Dateien befinden, so werden diese tatsächlich aufgelistet: panitz@ThinkPad-T430:~/fh/oose/v250107$ ls build build.properties~ build.xml~ docs web build.properties build.xml dist src panitz@ThinkPad-T430:~/fh/oose/v250107$ Es werden in diesem Fall 9 Dateien aufgelistet. Wenn wir mehr Informationen über diese Dateien erhalten wollen, so können wir dem Befehl ls einen zusätzlichen Befehlspara- meter mitgeben. Solche beginnen in der Regel mit einem Minuszeichen. ls kennt den Parameter -l, der für long steht und eine ausführliche Auflistung der Dateien bewirkt. 13 panitz@ThinkPad-T430:~/fh/oose/v250107$ ls -l insgesamt 60 drwxr-xr-x 3 panitz panitz 4096 Okt 6 2010 build -rw-r--r-- 1 panitz panitz 253 Okt 6 2010 build.properties -rw-r--r-- 1 panitz panitz 246 Okt 6 2010 build.properties~ -rw-r--r-- 1 panitz panitz 16334 Okt 6 2010 build.xml -rw-r--r-- 1 panitz panitz 16336 Okt 6 2010 build.xml~ drwxr-xr-x 3 panitz panitz 4096 Okt 6 2010 dist drwxr-xr-x 2 panitz panitz 4096 Okt 6 2010 docs drwxr-xr-x 2 panitz panitz 4096 Okt 6 2010 src drwxr-xr-x 3 panitz panitz 4096 Okt 6 2010 web panitz@ThinkPad-T430:~/fh/oose/v250107$ Zusätzlich werden jetzt zu jeder Datei eine ganze Reihe weiterer Informationen ange- zeigt. Für jede Datei wird dazu eine Zeile ausgegeben. Zusätzliche Informationen sind die Benutzerrechte der Datei, die Dateigröße, das Datum der letzten Änderung und die Angabe, ob es sich bei der Datei um einen Ordner handelt. Es gibt Dateien, die der Befehl ls normaler Weise nicht anzeigt, die sogenannten versteck- ten Dateien. Eine Datei gilt als versteckt, wenn ihr Name mit einem Punkt beginnt. Fügt man dem Befehl ls den Paramter -a hinzu, werden alle, auch die versteckten Dateien, aufgelistet. panitz@ThinkPad-T430:~/oose$ ls panitz@ThinkPad-T430:~/oose$ ls -a....versteckt panitz@ThinkPad-T430:~/oose$ ls -a -l insgesamt 20 drwxrwxr-x 2 panitz panitz 4096 Sep 18 11:27. drwxr-xr-x 286 panitz panitz 16384 Sep 16 14:16.. -rw-rw-r-- 1 panitz panitz 0 Sep 18 11:27.versteckt panitz@ThinkPad-T430:~/oose$ Wie man hier sieht, wurde durch ls keine Datei aufgelistet. Der zusätzliche Parameter -a bewirkt, dass drei zusätzliche Dateien aufgelistet werden, die jeweils mit einem Punkt im Namen beginnen. -a -l zeigt, dass zwei dieser versteckten Dateien Ordner sind. Auf der ursprünglich aus DOS stammenden Kommandozeile der Microsoft Betriebssys- teme heißt der analoge Befehl zum Auflisten der Dateien dir. cd Wechseln des Arbeitsverzeichnisses Wir haben festgestellt, dass sich alle Befehle der Kommandozeile auf das Arbeitsver- zeichnis beziehen. Da man natürlich nicht immer mit den Dateien eines festen Arbeits- verzeichnisses arbeiten möchte, gibt es einen Befehl zum Wechseln des Arbeitsverzeich- nisses. Dieses ist der Befehl cd, der für change directory steht. Er bekommt als Argument den Ordner angegeben, in den man wechseln möchte. 14 panitz@ThinkPad-T430:~$ panitz@ThinkPad-T430:~$ cd oose panitz@ThinkPad-T430:~/oose$ In diesen Beispiel wird in den Unterordner oose des aktuellen Arbeitsverzeichnisses ge- wechselt. Anschließend ist dieser das neue Arbeitsverzeichnis. Im Prompt der Komman- dozeile, das ist die Meldung, mit der eine Eingabe erwartet wird, wird angezeigt, welches das aktuelle Arbeitsverzeichnis ist. Es ist natürlich nicht nur möglich in einen bestimmten Unterordner zu wechseln. Man kann auch weiter in den übergeordneten Ordner wechseln. Dieser Ordner hat einen re- servierten Namen, aus zwei Punkten. panitz@ThinkPad-T430:~/oose$ cd.. panitz@ThinkPad-T430:~$ Es gibt einen weiteren besonderen Ordner. Dieses ist das Heimatverzeichnis des Benut- zers. In diesem Heimatverzeichnis startet auch standardmäßig die Kommandozeile. Dieses ist das Startverzeichnis, in dem der Benutzer seine eigenen Dateien speichert. Es wird mit dem Tildesymbol ~ bezeichnet. panitz@ThinkPad-T430:~/oose$ cd ~ panitz@ThinkPad-T430:~$ In dieses Verzeichnis wechselt der Befehl cd auch, wenn kein Ordner angegeben wird, in dem gewechselt werden soll. panitz@ThinkPad-T430:~/oose$ cd panitz@ThinkPad-T430:~$ Es ist nicht nur möglich, relativ vom aktuellen Arbeitsverzeichnis in ein Unterverzeichnis oder das Elternverzeichnis zu wechseln, sondern man kann auch absolut von der Wurzel des Dateisystems aus einen Pfad in ein bestimmtes Verzeichnis angeben. Dann ist voll- kommen egal, in welchen Arbeitsverzeichnis sich die Kommandozeile bei Ausführung des Befehls befindet. Ein absoluter Pfad beginnt mit einem Schrägstrich /, der die Wurzel des gesamten Dateisystems bezeichnet. Ausgehend von dieser kann nun eine Folge von Ordnern angegeben werden, die durch einen Schrägstrich getrennt werden. panitz@ThinkPad-T430:~$ cd /home/panitz/fh/oose/v250107/ panitz@ThinkPad-T430:~/fh/oose/v250107$ Ein Pfad muss aber wiederum nicht absolut von der Wurzel des Dateisystems begin- nen, sondern kann auch relativ vom Arbeitsverzeichnis beginnen. Hierzu ist der erste 15 Schrägstrich wegzulassen. panitz@ThinkPad-T430:~/fh/oose/v250107$ cd../../pmt/v270513/ panitz@ThinkPad-T430:~/fh/pmt/v270513$ So wie es mit den zwei Punkten die Möglichkeit gibt, das übergeordnete Verzeichnis anzugeben, kann man auch das aktuelle Verzeichnis angeben. Hierzu dient der einfache Punkt. ls mit Pfadangaben Nachdem wir nun die Pfadangaben für die Kommandozeile kennen gelernt haben, können wir diese auch für den Befehl ls anwenden. Bisher haben wir uns von ls immer nur eine Auflistung der Dateien des Arbeitsverzeichnisses geben lassen. Wir können aber durch Angabe eines Pfades, der einen bestimmten Ordner bezeichnet, ls dazu bringen, die Dateien in diesem Ordner anzuzeigen. panitz@ThinkPad-T430:~/fh/pmt/v270513$ ls /home/panitz/fh/oose/vor130605/ Counter.class GUI$3.class Inner.java~ Counter.java GUI.class KnopfAktion.class Counter.java~ GUI.java KnopfAktion.java EverySecond.class GUI.java~ KnopfAktion.java~ EverySecond.java Inner$1.class MyGraphic.class EverySecond.java~ Inner$1InnerInner.class MyGraphic.java GUI$1.class Inner.class MyGraphic.java~ GUI$1KnopfAktion.class Inner$InnerInner.class GUI$2.class Inner.java panitz@ThinkPad-T430:~/fh/pmt/v270513$ Sollte man nur an Informationen einer bestimmten Datei interessiert sein, so lässt sich dieses durch einen Pfad auf diese Datei,bestimmen. panitz@ThinkPad-T430:~$ ls -l /home/panitz/fh/oose/GUI.java -rw-r--r-- 1 panitz panitz 1111 Okt 6 2010 ,→ /home/panitz/fh/oose/GUI.java panitz@ThinkPad-T430:~$ Innerhalb von Dateinamen hat der Stern * noch eine besondere Bedeutung. Er steht für eine beliebige Folge von beliebigen Buchstaben. So bedeutet z.B. *.jpg alle Dateinamen mit der Endung.jpg. So lassen sich Mengen von Dateien ansprechen. Im folgenden Beispiel werden alle Dateien angezeigt, deren Name mit GUI beginnt und die die Endung.class haben. 16 panitz@ThinkPad-T430:~$ ls -l /home/panitz/GUI*.class -rw-r--r-- 1 panitz panitz 875 Okt 6 2010 /home/panitz/GUI$1.class -rw-r--r-- 1 panitz panitz 875 Okt 6 2010 /home/panitz/GUI$2.class -rw-r--r-- 1 panitz panitz 585 Okt 6 2010 /home/panitz/GUI$3.class -rw-r--r-- 1 panitz panitz 1655 Okt 6 2010 /home/panitz/GUI.class panitz@ThinkPad-T430:~$ mkdir Neue Verzeichnisse Anlegen Es lassen sich mit dem Befehl mkdir neue Verzeichnisse anlegen. Hierzu schreibt man hinter den Befehl als Pfadangabe den Namen des anzulegenden Verzeichnisses. Dieses kann wieder relativ zu dem Arbeitsverzeichnis oder auch eine absolute Pfadangabe sein. panitz@ThinkPad-T430:~$ mkdir neuesTestVerzeichnis panitz@ThinkPad-T430:~$ cd neuesTestVerzeichnis/ panitz@ThinkPad-T430:~/neuesTestVerzeichnis$ Mit dem Befehl rmdir lassen sich Verzeichnisse wieder löschen. Hierzu muss das Verzeich- nis allerdings leer sein. Es darf keine Unterverzeichnisse oder Dateien mehr enthalten. panitz@ThinkPad-T430:~/neuesTestVerzeichnis$ cd.. panitz@ThinkPad-T430:~$ rmdir neuesTestVerzeichnis/ panitz@ThinkPad-T430:~$ touch Neue Dateien Anlegen oder Dateien Aktualisieren Es lassen sich auch neue leere Dateien von der Kommandozeile anlegen. Hierzu kann der Befehl touch benutzt werden. Ihm gibt man an, welche Datei neu angelegt werden soll. panitz@ThinkPad-T430:~/neuesTestVerzeichnis$ ls -l insgesamt 0 panitz@ThinkPad-T430:~/neuesTestVerzeichnis$ touch neueTestdatei panitz@ThinkPad-T430:~/neuesTestVerzeichnis$ ls -l insgesamt 0 -rw-rw-r-- 1 panitz panitz 0 Sep 19 10:33 neueTestdatei panitz@ThinkPad-T430:~/neuesTestVerzeichnis$ Sollte der Befehl für eine Datei aufgerufen werden, die bereits existiert, so wird der Dateiinhalt nicht verändert, aber das Datum der letzten Änderung aktualisiert. 17 panitz@ThinkPad-T430:~/neuesTestVerzeichnis$ ls -l insgesamt 0 -rw-rw-r-- 1 panitz panitz 0 Sep 19 10:33 neueTestdatei panitz@ThinkPad-T430:~/neuesTestVerzeichnis$ touch neueTestdatei panitz@ThinkPad-T430:~/neuesTestVerzeichnis$ ls -l insgesamt 0 -rw-rw-r-- 1 panitz panitz 0 Sep 19 10:34 neueTestdatei panitz@ThinkPad-T430:~/neuesTestVerzeichnis$ cat, more und less Dateiinhalte Anzeigen Auch der Inhalt einer Textdatei lässt sich auf der Kommandozeile anzeigen. Hierzu kann der Befehl cat benutzt werden. cat steht dabei für concatenate, also zum Konkatenieren, dem Aneinanderhängen von Dateiinhalten. Der Name kommt daher, dass dem Befehl cat nicht nur eine sondern eine Liste von Dateien angegeben werden kann. Es werden dann die Inhalte dieser Dateien nacheinander auf der Kommandozeile ausgegeben. panitz@ThinkPad-T430:~/neuesTestVerzeichnis$ cat neueTestdatei Hier steht nur ein kleiner Beispieltext. panitz@ThinkPad-T430:~/neuesTestVerzeichnis$ Ist eine Textdatei sehr groß, so flutscht die Ausgabe von cat sehr schnell auf der Kom- mandozeile vor unserem Auge vorbei. Man will einen Dateiinhalt in der Regel durchlesen. Hierzu gibt es die funktionsgleichen Programme more und less. Auch mit diesen Befeh- len wird der Dateiinhalt auf der Kommandozeile ausgegeben. Allerdings immer nur eine Seite, die genau auf das Fenster der Kommandozeile passt. Nun kann man mit Drücken der Leertaste jeweils zur nächsten Seite springen. Mit Drücken der Taste Q wird die Anzeige der Datei beendet. pwd Pfadangabe Man kann sich durch den Befehl pwd den absoluten Pfad zum Arbeitsverzeichnis anzeigen lassen. panitz@ThinkPad-T430:~/neuesTestVerzeichnis$ pwd /home/panitz/neuesTestVerzeichnis panitz@ThinkPad-T430:~/neuesTestVerzeichnis$ rm Dateien Löschen Dateien lassen sich auch löschen. Hierzu dient der Befehl rm, der memotechnisch für remove steht. (Auf der Kommandozeile für Microsoft Betriebssysteme heißt der entspre- chende Befehl del.) Dieser Befehl ist nichts für Feiglinge, denn die mit ihm gelöschten 18 Dateien sind unwiederbringlich weg. Sie sind nicht in einem Papierkorb zwischengelagert, aus dem sie wieder reaktiviert werden können. Besonders gefährlich kann es sein, wenn dieser Befehl mit einer Dateiangabe aufgerufen wird, die über das Sternsymbol mehrere Dateien bezeichnet. rm *.jpg *.gif *.png löscht zum Beispiel alle Bilddateien im Ar- beitsverzeichnis. rm * löscht alle Dateien im Arbeitsverzeichnis. Der Befehl kennt dann noch den Parameter -r. Er steht dafür, dass im Falle eines Ordners zunächst alle Dateien und Unterordner dieses Ordners zu löschen sind und dann der Ordner selbst. So löscht also rm -r * alle Dateien und alle Ordner komplett aus dem Arbeitsverzeichnis. In Ihrem Heimatverzeichnis aufgerufen löschen Sie damit also alle Ihre Dateien. Also Vorsicht! mv Dateien Umbenennen und Verschieben Der Befehl mv steht memotechnisch für move. Er dient dazu, eine Datei an einen anderen Ort, also in einen anderen Ordner, zu verschieben. Er hat aber auch eine zweite verwandte Funktionalität. Er dient auch dazu eine Datei umzubenennen. Mindestens zwei Parameter sind diesem Befehl anzugeben. Die Datei, die verschoben oder umbenannt werden soll, und das Ziel wohin diese verschoben werden soll. Ist das Ziel ein existierender Ordner im Dateisystem, so wird die Datei dahin verschoben. Ist es ein Dateiname einer noch nicht existierenden Datei, dann wird die Datei umbenannt. panitz@ThinkPad-T430:~/oose$ ls testdatei.txt panitz@ThinkPad-T430:~/oose$ mv testdatei.txt neuerName.txt panitz@ThinkPad-T430:~/oose$ ls neuerName.txt panitz@ThinkPad-T430:~/oose$ mkdir einNeuerOrdner panitz@ThinkPad-T430:~/oose$ mv neuerName.txt einNeuerOrdner/ panitz@ThinkPad-T430:~/oose$ ls einNeuerOrdner panitz@ThinkPad-T430:~/oose$ cd einNeuerOrdner/ panitz@ThinkPad-T430:~/oose/einNeuerOrdner$ ls neuerName.txt panitz@ThinkPad-T430:~/oose/einNeuerOrdner$ Auch hier muss man ein wenig Vorsicht walten lassen. Existiert die Zieldatei bereits, so wird sie mit der Quelldatei überschrieben und damit quasi gelöscht. Man kann den Befehl mv auch nutzen, um mehrere Dateien in einen Ordner zu verschie- ben. Dann erhält der Befehl mehr als zwei Argumente. Das letzte Argument bezeichnet dabei einen Ordner, in den die vorherigen Argumente zu verschieben sind. Auch hier kann man sich wieder des Sterns bedienen. So bewirkt mv *.jpg meineBilder, dass alle Dateien des Arbeitsverzeichnisses mit der Endung jpg in den Unterordner meineBilder verschoben werden. 19 cp Dateien Kopieren Sehr ähnlich, wie der Befehl mv funktioniert der Befehl cp, der dazu dient eine oder mehrere Dateien zu kopieren. Es handelt sich dazu im Prinzip um den gleichen Befehl wie mv, nur wird die Quelldatei in diesem Fall nicht gelöscht. Damit gibt es anschließend also zwei unabhängige Versionen der Quelldatei. man Handbuchseiten Wie kann man sich alle diese Befehle und ihre Benutzung merken. Alle diese kleinen Parameter. Die Antwort ist: RTFM. Dieses steht für den Satz read the fucking manual also eine etwas saloppe Aufforderung, das Handbuch zu lesen. Mit dem Befehl man können die Handbucheinträge aller Befehle aufgerufen werden. Wer z.B. nicht mehr weiß, wie der Befehl ls genau funktioniert, kann das mit man ls erfragen und bekommt folgende Ausgabe: panitz@ThinkPad-T430:~/neuesTestVerzeichnis$ man ls LS(1) User Commands ,→ LS(1) NAME ls - list directory contents SYNOPSIS ls [OPTION]... [FILE]... DESCRIPTION List information about the FILEs (the current directory by ,→ default). Sort entries alphabetically if none of -cftuvSUX nor --sort is ,→ speci- fied. Mandatory arguments to long options are mandatory for short ,→ options too. -a, --all do not ignore entries starting with. -A, --almost-all do not list implied. and.. --author Manual page ls(1) line 1 (press h for help or q to quit) 20 Wie sie sehen, gibt es mehr Optionen für diesen Befehl, als in diesem Skript angegeben. Das gilt für alle der hier vorgestellten Befehle. Es lässt sich auch die Hilfe für die gesamte Kommandozeilenbenutzung anzeigen durch man bash. 1.3.2 Nützliche Standardprogramme Im letzten Abschnitt haben wir die wichtigsten Befehle der Kommandozeile zum Um- gang mit dem Dateisystem kennen gelernt. Prinzipiell kann jedes Programm über die Kommandozeile gestartet werden. Viele Programme haben selbst gar keine graphische Benutzerschnittstelle sondern sind zur Benutzung über die Kommandozeile vorgesehen, oder werden von anderen Programmen aus gestartet. In diesem Abschnitt sollen ein paar elementare Programme, die sehr nützlich sind, kurz vorgestellt werden. Sicheres Einloggen auf anderen Rechner mit ssh Das Programm ssh dient dazu, um sich auf einem Rechner über ein Netzwerk einzulog- gen und quasi die dortige Kommandozeile zu benutzen. Dieses ist natürlich besonders nützlich, wenn man einen Webserver warten möchte. Hierzu ist beim Aufruf von ssh der Rechnername des Rechners, auf den man sich einloggen möchte, als Argument anzugeben. Wir haben bei uns im Studienbereich den Rechner mit der Adresse login1.cs.hs-rm.de, auf dem Sie sich mit Ihrem Passwort einloggen können. Um anzugeben, als welcher Be- nutzer Sie sich auf dem Rechner einloggen wollen, können Sie Ihren Benutzernamen mit dem Klammeraffensymbol getrennt dem Rechnernamen voranstellen. panitz@ThinkPad-T430:~/oose$ ssh [email protected] [email protected]'s password: The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. Last login: Tue Oct 1 12:10:22 2013 from vpn501.hotsplots.net panitz@fozzie(~)$ Jetzt arbeiten Sie auf dem Server. Dieses erkennen Sie zum Beispiel, wenn Sie jetzt den Befehl ls eintippen, denn dann stellen Sie fest, dass Sie die Dateien an der Hochschule und nicht auf Ihrem Rechner daheim sehen. Wollen Sie die Verbindung mit dem fremden Rechner beenden, so können Sie das durch den Befehl exit: 21 panitz@fozzie(~)$ exit Abgemeldet Connection to login1.cs.hs-rm.de closed. panitz@ThinkPad-T430:~/oose$ Transfer von Dateien mit sftp Mit ssh können Sie auf die Kommandozeile eines Rechners über ein Netzwerk zugreifen. Manchmal will man aber eine oder mehrere Dateien von einem anderen Rechner holen oder auf einen anderen Rechner hoch laden. Hierzu dient das Programm sftp (secure file transfer program). Auch dieses wird mit Ihrem Benutzernamen gefolgt von der Adresse des Servers gestartet. Wenn Sie in den Server eingeloggt sind, sind sie in einer Umgebung, in der Sie Befehle zum Dateitransfer abschicken können. Die Befehle heißen put, um Da- teien auf den Server hochzuladen und get um Dateien von dem Server herunterzuladen. Mit dem aus der Kommandozeile bekannten Befehl cd können Sie durch das Dateisystem des Servers navigieren. panitz@ThinkPad-T430:~/oose/einNeuerOrdner$ sftp ,→ [email protected] [email protected]'s password: Connected to login1.cs.hs-rm.de. sftp> put existierendeDatei Uploading existierendeDatei to /home/staff/panitz/existierendeDatei existierendeDatei 100% 0 0.0KB/s 00:00 sftp> get Main.hs Fetching /home/staff/panitz/Main.hs to Main.hs sftp> exit panitz@ThinkPad-T430:~/oose/einNeuerOrdner$ Auch dieses Programm wird durch die Eingabe des Befehls exit wieder beendet. Kopieren über Rechnergrenzen mit scp Statt mit dem Programm sftp können Sie auch mit der Anweisung scp von einem auf einen anderen Rechner kopieren. Ziel oder Quelle dieses Kopierbefehls können auf einem entfernten Rechner liegen. Hierzu wird dem Rechnernamen des entfernten Rechners nach einem Doppelpunkt der Pfad im dortigen Dateisystem angegeben. Auch hier wird vor dem Rechnernamen mit dem Klammeraffen getrennt der Anwendername auf diesem Rechner angegeben. 22 $ scp -P 2200 target/LectureNotes-1.0-SNAPSHOT.war ,→ [email protected]:~ [email protected]'s password: LectureNotes-1.0-SNAPSHOT.war 49% 8336KB 62.7KB/s 02:17 ,→ ETA Dateityp erfragen mit file Eigentlich sollte der Typ einer Datei durch die Dateiendung korrekt angegeben sein. Manchmal fehlt aus unerfindlichen Gründen diese Endung, oder aber, sie wurde falsch angegeben (Das passiert immer wieder bei Abgaben von studentischen Lösungen). Oder aber man kennt die Endung nicht. Dann ist das Programm file recht nützlich, denn es versucht herauszubekommen, um was für eine Datei es sich handelt. panitz@ThinkPad-T430:~$ file FKT_Programm_11_13_V1_Montageflaechen-1 FKT_Programm_11_13_V1_Montageflaechen-1: PDF document, version 1.4 panitz@ThinkPad-T430:~$ Dateien in ein Archiv verpacken mit tar Zur Archivierung oder dem Versand von einer großen Menge von Dateien, zum Beispiel aller Ihrer Urlaubsbilder, empfiehlt es sich, diese in einer einzigen Archivdatei zu bündeln und am besten noch zu komprimieren. Hierzu gibt es mehrere Programme und daraus resultierende Dateiformate wie zum Beispiel das Programm zip. Ein Standardprogramm auf der Unix-Welt ist hierzu das Programm tar. Es steht für tape archive und deutet so im Namen auf die Zeiten hin, als Daten auf Tonbändern archiviert wurden. Dem Programm tar wird durch eine Folge von Buchstaben beim Aufruf angegeben, was es machen soll, z.B. ob es ein neues Archiv erzeugen oder ob es ein bestehendes entpacken soll. Dann folgen die Dateien, mit denen gearbeitet werden soll. Das Erzeugen eines neuen Archivs wird durch den Buchstaben c für create angegeben. Mit dem Buchstaben f wird angegeben, dass jetzt der Name der Archivdatei folgt. Will man also alle Bilddateien im Arbeitsverzeichnis in eine Archivdatei bilder.tar verpacken, so geht das mit dem Befehl tar cf bilder.tar *.jpg. Zum Entpacken einer Archivdatei benutzt man den Buchstaben x für extract statt des Buchstabens c. Die mit obigen Befehl erzeugte Archivdatei lässt sich also mit tar xf bilder.tar wieder entpacken. Will man sich nur eine Auflistung der Dateien, die in einer Archivdatei verpackt wurden, geben lassen, so nimmt man den Buchstaben t für table. Fügt man noch den Buchstaben v für verbode hinzu, so gibt das Programm etwas mehr Ausgaben. Soll die Archivdatei komprimiert werden, so füge man noch den Buchstaben z hinzu. 23 Hier ein kleines Beispiel zum Verpacken, Auflisten und Entpacken einer kleinen Archiv- datei: panitz@ThinkPad-T430:~/Bilder$ tar cvzf bilder.tgz *.png Bildschirmfoto1.png Bildschirmfoto2.png Bildschirmfoto3.png Logo-gross.png tree.png panitz@ThinkPad-T430:~/Bilder$ tar tvzf bilder.tgz -rw-rw-r-- panitz/panitz 368235 2013-07-17 19:05 Bildschirmfoto1.png -rw-rw-r-- panitz/panitz 157235 2013-08-01 19:49 Bildschirmfoto2.png -rw-rw-r-- panitz/panitz 156051 2013-08-01 21:59 Bildschirmfoto3.png -rw-r--r-- panitz/panitz 14209 2009-01-03 14:47 Logo-gross.png -rw-rw-r-- panitz/panitz 3733 2013-05-14 15:25 tree.png panitz@ThinkPad-T430:~/Bilder$ tar xvzf bilder.tgz Bildschirmfoto vom 2013-07-17 19:05:30.png Bildschirmfoto vom 2013-08-01 19:49:16.png Bildschirmfoto vom 2013-08-01 21:59:44.png Logo-gross.png tree.png panitz@ThinkPad-T430:~/Bilder$ Weitere Tipps und Tricks Den ersten und rudimentären Umgang mit der Kommandozeile haben wir eingeübt. Arbeiten mit Vervollständigung und Befehlshistorie Die Kommandozeile merkt sich die bereits ausgeführten Befehle. Oft will man einen ähnlichen oder den gleichen Befehl noch einmal ausführen lassen. Die Pfeiltasten liefern heute eine einfache Möglichkeit durch die Befehlshistorie zu navigieren und zuvor bereits ausgeführte Befehle wieder anzeigen lassen. Auch die Tabulatortaste vereinfacht die Arbeit mit der Kommandozeile und hilft dabei, weniger eintippen zu müssen. Wenn von der Kommandozeile der Name einer Datei er- wartet wird, kann man die ersten Buchstaben der Datei tippen und dann mit Hilfe der Tabulatortaste sich den kompletten Dateinamen vervollständigen zu lassen. So müssen lange Dateinamen nicht komplett eingetippt werden. Umleiten der Ausgabe in eine Datei Wenn man einen Befehl startet, der eine ausführ- liche Ausgabe auf der Kommandozeile macht, dann kann man diese auf einfache Wei- se von der Kommandozeile in eine Datei schreiben lassen. Hierzu bedient man sich des Größer-Zeichens. Nach dem Befehl wird das Größer-Zeichen und der Dateiname geschrie- ben. Dieses bewirkt, dass die Ausgabe des Befehls nicht mehr auf der Kommandozeile angezeigt wird, sondern in die angegebene Datei geschrieben wird. 24 Zwei Programme verbinden Ein besonders eleganter Trick ist es, die Ausgabe eines Befehls direkt wieder als Eingabe für einen weiteren Befehl zu benutzen. Hierzu dient die sogenannte pipe, die durch einen vertikalen Strich bezeichnet wird. Ist das Arbeitsverzeichnis zum Beispiel ein Ordner, in dem sehr viele Dateien liegen, dann führt der Befehl ls -l zu einer umfangreichen Ausgabe auf der Kommandozeile, die schnell auf dem Bildschirm vorbei rauscht. Jetzt kann man die Ausgabe von ls -l direkt an das Programm less weiterleiten, indem man die Ausgabe von ls dem Befehl less über eine pipe direkt als Eingabe gibt. Der gesamte Aufruf lautet dann ls -l | less. 1.3.3 Erste Java Programme auf der Kommandozeile In diesem Abschnitt soll gezeigt werden, wie prinzipiell Programme auf der Komman- dozeile entwickelt werden. Wir erinnern uns, dass ein Programm zunächst einmal nichts weiter als ein Text ist. Wir müssen also einen Text schreiben. Dieser Text ist dann von einem besonderen Programm in eine Maschinensprache zu übersetzen. Ein solches Pro- gramm heißt Kompilator (eng. compiler). Der Kompilator untersucht den Quelltext und übersetzt diesen, sofern das möglich ist, in eine oder mehrere binäre Dateien, die Befehle für eine Maschine codieren. Schließlich müssen diese binären Dateien zur Ausführung auf einer Maschine gebracht werden. Quelltext editieren Wir benötigen ein Programm, das uns erlaubt, eine Quelltextdatei zu erstellen. Ein sol- ches Programm nennt man einen Texteditor. Dieser ist nicht zu verwechseln mit einem Textverarbeitungsprogramm, in dem nicht nur Text, sondern auch ein Layout mit Schrift- arten, Schriftgrößen etc. erstellt wird. Es gibt tatsächlich Programme, die dieses alleine auf der Kommandozeile ohne eine graphische Benutzeroberfläche erlauben. Der Stan- dardeditor für die Kommandozeile heißt vi. Es gibt sogar auch heute noch Leute, die nur mit Hilfe des vi ihre Programme schreiben. Aber gerüchteweise sollen das nur noch fusselige, bärtige, nuschelnde, selbstdrehende Systemadministratoren sein. Trotzdem sollte jeder Informatiker den rudimentären Umgang mit dem Programm vi kennen, denn irgendwann in seiner Laufbahn wird der Moment kommen, an dem er schnell eine Konfigurationsdatei ändern muss, aber nur einen Kommandozeilenzugang zu dem Rechner hat. Das Programm vi kann gestartet werden mit dem Namen der Datei, die man editieren möchte. Existiert keine Datei mit diesen Namen, so wird die Datei dann neu angelegt. Wenn wir also eine Javaquelltextdatei mit dem Dateinamen FirstProgram.java editie- ren und erstellen möchten, so starten wir den vi mit dem Befehl: vi FirstProgram.java 25 Das Programm vi hat zwei Modi. Den Befehlsmodus, in dem jede Eingabe als Befehl für den Editor interpretiert wird, und den Einfügemodus, in dem jede Eingabe als Text für den Inhalt der Datei interpretiert wird. Der Befehlsmodus ersetzt die Menüs, die aus den Texteditoren mit graphischer Benutzerführung bekannt sind. Vom Befehlsmodus kann man in den Einfügemodus durch Eingabe von i für insert oder a für append wechseln. Nach der Eingabe des Befehls i befindet man sich in Einfügemodus und alle folgenden Buchstaben werden vor der markierten Stelle des Dokuments einge- fügt. Nach dem Befehl a werden beim Einfügemodus alle folgenden Buchstaben nach der ursprünglich markierten Stelle eingefügt. Vom Einfügemodus in den Befehlsmodus wechselt man durch Drücken der ESC-Taste. Die wichtigsten Befehlsfolgen im Befehlsmodus betreffen natürlich das Speichern der Da- tei und auch das Verlassen des Programms. Diese Befehlsfolgen werden durch den Dop- pelpunkt eingeleitet. Der Befehl :wq bewirkt im Befehlsmodus, dass die Datei gespeichert wird (w für write) und das Programm vi verlassen wird (q für quit). Versuchen Sie also, Ihre erste Javaquelltextdatei mit dem vi zu schreiben. Jede Ja- vaquelltextdatei hat die Endung.java. In einer Javaquelltextdatei wird jeweils genau eine sogenannte Klasse definiert. Folgendes ist die kleinste mögliche Klasse. Sie heißt FirstProgram und ist entsprechend in eine Datei FirstProgramm.java zu speichern. FirstProgramm.java class FirstProgramm{ } Es gibt noch eine ganze Reihe weiterer Texteditoren, die auf der Kommandozeile be- nutzt werden können. Ich persönlich benutze wann immer möglich das Programm emacs, welches mit einer Menüführung daherkommt, aber auch einen Modus hat, der ohne gra- phische Benutzeroberfläche auskommt. Hierzu startet man den emacs mit dem Argument -nw (für no window). Ein weiteres solcher Texteditor ist das Programm joe. Allerdings sind emacs oder joe nicht auf allen Systemen installiert, wohingegen man eigentlich immer davon ausgehen kann, dass vi existiert. Quelltext kompilieren Nun brauchen wir den Kompilator, der einen Quelltext in einen binären Maschinencode überführt. Für Java heißt das entsprechende Programm javac. Durch den Aufruf des Programms javac kann man sich davon überzeugen, dass die Java-Entwicklerumgebung auf dem Rechner installiert ist. Ruft man den Kompilator auf, so macht er folgende Ausgabe, die über seine Benutzung informiert: 26 panitz@ThinkPad-T430:~$ javac Usage: javac where possible options include: -g Generate all debugging info -g:none Generate no debugging info -g:{lines,vars,source} Generate only some debugging info -nowarn Generate no warnings -verbose Output messages about what the compiler is ,→ doing -deprecation Output source locations where deprecated APIs ,→ ar -classpath Specify where to find user class files and ,→ annot -cp Specify where to find user class files and ,→ annot -sourcepath Specify where to find input source files -bootclasspath Override location of bootstrap class files -extdirs Override location of installed extensions -endorseddirs Override location of endorsed standards path -proc:{none,only} Control whether annotation processing and/or ,→ com -processor [,,...] Names of the annotation ,→ processo -processorpath Specify where to find annotation processors -d Specify where to place generated class files -s Specify where to place generated source files -implicit:{none,class} Specify whether or not to generate class ,→ files f -encoding Specify character encoding used by source ,→ files -source Provide source compatibility with specified ,→ rele -target Generate class files for specific VM version -version Version information -help Print a synopsis of standard options -Akey[=value] Options to pass to annotation processors -X Print a synopsis of nonstandard options -J Pass directly to the runtime system -Werror Terminate compilation if warnings occur @ Read options and filenames from file panitz@ThinkPad-T430:~$ Wie man dieser Ausgabe entnehmen kann, gibt es das Argument -version, mit dem die Versionsnummer des Kompilators erfragt werden kann. 27 panitz@ThinkPad-T430:~$ javac -version javac 11.0.4 panitz@ThinkPad-T430:~$ In diesem Fall handelt es sich also um den Java-Kompilator für Java der Version 11.0.4 Jetzt können wir für die Java-Quelltextdatei FirstProgram.java durch den Kompilator in eine binäre Datei übersetzen lassen. Hierzu wird der Kompilator mit dem Dateinamen der Quelltextdatei als Argument aufgerufen. Das Ergebnis ist im Erfolgsfall eine neu generierte Datei, die class-Datei. panitz@ThinkPad-T430:~/oose$ ls FirstProgram.java panitz@ThinkPad-T430:~/oose$ javac FirstProgram.java panitz@ThinkPad-T430:~/oose$ ls FirstProgram.java FirstProgram.class panitz@ThinkPad-T430:~/oose$ Wie man sieht, wurde die Quelltextdatei erfolgreich übersetzt und eine Class-Datei er- zeugt. Sehr oft ruft man den Kompilator auf, doch statt den Quelltext zu übersetzen, bricht er mit einer Fehlermeldung ab. Dieses ist der Fall, wenn in der Quelltextdatei kein gültiges Java-Programm geschrieben ist. In unseren Fall war aber der Übersetzungsvor- gang erfolgreich. Programme ausführen Schließlich soll die binäre Datei mit den Maschinenbefehlen, ausgeführt werden. Im Falle von Java handelt es sich dabei nicht um eine real als Hardware existierende Maschi- ne, sondern um eine gedachte, eine sogenannte virtuelle Maschine. Diese wird durch ein Programm realisiert. Daher braucht man zum Ausführen von Javaprogrammen das Pro- gramm, das die virtuelle Maschine realisiert. Dieses Programm heißt sinniger Weise java. Auch in diesem Fall kann man sich durch den Befehl java auf der Kommandozeile davon überzeugen, dass die virtuelle Maschine auf dem Rechner installiert ist. Das Programm java wird auch als Javainterpreter bezeichnet. Der Javainterpreter wird aufgerufen mit dem Namen der Klasse, die ausgeführt werden soll. Hierbei wird kein Dateiname angegeben, auch keine Dateiendung, sondern nur der Name der Klasse, in unserem Fall FirstProgram. Somit ist der Befehl zum Ausführen der Klasse java FirstProgram. Rufen wir dieses auf, so stellen wir fest, dass der Javainterpreter eine Fehlermeldung ausgibt: 28 panitz@ThinkPad-T430:~/oose$ java FirstProgram Fehler: Hauptmethode in Klasse FirstProgram nicht gefunden. Definieren Sie die Hauptmethode als: public static void main(String[] args) panitz@ThinkPad-T430:~/oose$ In diesem Fall ist die Meldung sogar auf Deutsch. Sie besagt, dass der Klasse etwas fehlt, nämlich eine sogenannte Hauptmethode, in der die Javabefehle stehen, die ausgeführt werden sollen. Die Fehlermeldung gibt sogar an, wie eine solche Hauptmethode auszu- sehen hat. Schreiben wir jetzt einmal eine zweite Klasse, die eine solche Hauptmethode beinhaltet: SecondProgram.java class SecondProgram{ public static void main(String[] args){ } } Übersetzen wir diese Klasse mit dem Kompilator und interpretieren sie mit dem Ja- vainterpreter, so gibt es keine Fehlermeldung mehr. Allerdings passiert auch nichts, weil innerhalb der Hauptmethode keine Befehle stehen, die ausgeführt werden sollen. panitz@ThinkPad-T430:~/oose$ javac SecondProgram.java panitz@ThinkPad-T430:~/oose$ java SecondProgram panitz@ThinkPad-T430:~/oose$ Der erste und einfachste Befehl, mit dem man ein Programm dazu bringen kann, eine Rückmeldung an den Anwender zu geben, ist die Ausgabe eines Textes auf der Komman- dozeile. In Java ist dieser Befehl: System.out.println(). In die runden Klammern ist der Text zu schreiben, der ausgegeben werden soll. Text wird dabei in Java in doppelten Anführungszeichen gesetzt. Die folgende Javaklasse hat eine Hauptmethode innerhalb derer zweimal eine Zeile mit Text auf die Kommandozeile ausgegeben wird: ThirdProgram.java class ThirdProgram{ public static void main(String[] args){ System.out.println("Hallo Ilja!"); System.out.println("Hallo Welt!"); } } Kompilieren wir diese Klasse und interpretieren sie, so haben wir folgendes Verhalten: 29 panitz@ThinkPad-T430:~/oose$ javac ThirdProgram.java panitz@ThinkPad-T430:~/oose$ java ThirdProgram Hallo Ilja! Hallo Welt! panitz@ThinkPad-T430:~/oose$ 1.4 Interaktives Java mit der jshell Im letzten Abschnitt haben wir gesehen, wie man auf der Kommandozeile ein Javapro- gramm schreibt, kompiliert und ausführt. War Ihnen das alles zu kompliziert für den Einstieg. Dann gibt es eine schöne einfache Einstiegshilfe. Java hat auch einen interakti- ven Modus, die jshell. Die jshell ist ein Interpreter für Java, Sie erwartet eine Einga- be, wertet diese zu einem Ergebnis aus und zeigt dieses Ergebnis als Ausgabe an. Man spricht dabei auch von einer Read-Eval-Print-Loop kurz REPL. Manche Programmier- sprachen arbeiten allein mit einem solchen Interpreter, der einen direkten interaktiven Modus darstellt. Die Programmiersprache Python ist hierfür ein Beispiel. Manche Pro- grammiersprachen bieten nur einen Compiler an, der den Quelltext in ein ausführbares Programm übersetzt. Die Programmiersprache C ist ein Beispiel hierfür. Und manche Programmiersprachen bieten beides an: eine interaktive REPL und einen Compiler. Java zählt hierzu wie fast alle modernen Programmiersprachen auch. Die REPL von Java kann auf der Kommandozeile geöffnet werden mit dem Aufruf von jshell. Es öffnet sich die REPL, die eine Eingabe erwartet. Die einfachste Eingabe ist dabei wahrscheinlich eine Zahl. panitz@panitz-ThinkPad-T430:~$ jshell | Welcome to JShell -- Version 11.0.4 | For an introduction type: /help intro jshell> 1 $1 ==> 1 jshell> Das Ergebnis der Eingabe der Zahl 1 ist eben der Wert 1. Als zweiten Schritt können wir anfangen Rechnungen durchführen zu lassen. 30 jshell> 1+1 $2 ==> 2 jshell> 17+4*2 $3 ==> 25 jshell> Auf diese Art und Weise können wir spielerisch die ersten Schritte in Java machen und ein paar Java-Konstrukte kennenlernen. Bevor wir im Semester schrittweise systematisch die unterschiedlichen Konstrukte von Java kennenlernen, wollen wir zunächst einen intuitiven schnellen Einstieg mit der jshell wagen. Öffnen Sie also die jshell und spielen die folgenden Beispiele nach und machen weitere eigene Eingaben. 1.4.1 Ausdrücke auf Zahlen Wir haben bereits mit den ersten einfachen Rechnungen auf Zahlen begonnen. Die ein- fachste Rechnung ist die, in der nur eine konstante Zahl berechnet wird. ~$ jshell | Welcome to JShell -- Version 11.0.4 | For an introduction type: /help intro jshell> 42 $1 ==> 42 Das Ergebnis jeder Rechnung, die in der jshell durchgeführt wird, wird in einer Variablen gespeichert. Die Variablen werden durchnumeriert und beginnen mit dem Symbol $. Die jshell hat die Anweisung /vars, mit der sich alle Variablen und deren gespeicherte Werte anzeigen lassen: jshell> /vars | int $1 = 42 Wie man sieht, gibt es jetzt die Variable $1 mit dem Wert 42. Geben wir eine Rechnung mit Addition und Multiplikation ein. So wird diese ausgewertet. jshell> 17+4*2 $2 ==> 25 Und das Ergebnis in einer weiteren Variablen gespeichert. 31 jshell> /vars | int $1 = 42 | int $2 = 25 Wir können in der jshell die Werte von gespeicherten Variablen wieder Abfragen. Hierzu wird nur der Variablenname eingegeben. jshell> $1 $1 ==> 42 Ausdrücke, die ausgerechnet werden, können durch Klammern gruppiert sein. Damit lässt sich die Punkt- vor Strichrechnungsregel aus vorigen Beispiel umgehen. jshell> (17+4)*2 $3 ==> 42 Wir haben bisher nur mit ganzen Zahlen gerechnet. Um eine Rechnung auf Kommazahlen zu machen, muss eine beteiligte Zahl eine Kommazahl sein. jshell> (17+4)*2.0 $4 ==> 42.0 Wenn wir uns jetzt die gespeicherten Variablen anschauen erkennen wir, dass es zwei Arten von Zahlen zu geben scheint: jshell> /vars | int $1 = 42 | int $2 = 25 | int $3 = 42 | double $4 = 42.0 Die mit int markierten Variablen speichern ganze Zahlen, die mit double markierte Va- riable speichert eine Kommazahl. Dieses sind die ersten beiden Datentypen, die Sie sehen. In Java hat jede Variable einen fest definierten Datentypen, der nicht verändert werden darf und von Anfang an fest steht. Man sagt: Java ist statisch getypt. Die Programmier- sprache Python hingegen hat diese Eigenschaft nicht. Python ist eine dynamisch getypte Sprache. Die Unterscheidung von ganzen Zahlen und Kommazahlen wird bei der Division relevant: jshell> 17/4 $5 ==> 4 32 Wie man sieht erhält man eine ganze Zahl als Ergebnis. Erst wenn ein beteiligter Operand eine Kommazahl war, erhalten wir das Ergebnis mit der Nachkommazahl. jshell> 17/4.0 $6 ==> 4.25 Wenn man an den Rest einer Division interessiert ist, dann kann man sich diesen mit dem Operanden % errechnen lassen: jshell> 17%4 $7 ==> 1 Die 4 passt vier Mal in die 17 und es bleibt dann ein Rest von 1. Diese Rest-Operation der Division wird als Modulo-Operation bezeichnet. Sie funktioniert auch mit Kommazahlen, auch wenn sie da weniger sinnvoll ist. jshell> 17%4.0 $8 ==> 1.0 Mit diesen beiden Divisions-Operation lassen sich zum Beispiel die ersten und die letzten Stellen einer Zahl in Dezimalschreibweise leicht ermitteln. Die Rechnung %100 ergibt die Zahl aus den letzten beiden Ziffern: jshell> 1967%100 $9 ==> 67 Die Rechnung /100 ergibt die Zahl ohne den letzten beiden Ziffern: jshell> 1967/100 $10 ==> 19 jshell> 1.4.2 Arbeiten mit Variablen Das Ergebnis jeder Rechnung wird in der jshell in einer Variablen gespeichert. Diese sind durchnummeriert. Wenn Ihnen das nicht passt, können Sie aber auch explizit eigene Variablen für das Ergebnis anlegen: jshell> var x = 42 x ==> 42 33 Variablen können in weiteren Rechnungen verwendet werden: jshell> var x2 = 2*x+17 x2 ==> 101 Bestehende Variablen können auch einen neuen Wert bekommen: jshell> x = -1 x ==> -1 Und wer will kann den Wert einer Variablen in einer Rechnung verwenden und anschlie- ßend das Ergebnis als neuen Wert für dieselbe Variable verwenden. jshell> x = -x*17 x ==> 17 1.4.3 Vergleiche und Wahrheitswerte Wir können Zahlenwerte über ihre Größe vergleichen. Die folgende Berechnung vergleicht, ob der in x gespeicherte größer oder gleich dem in x2 gespeicherten Wert ist. jshell> x >= x2 $17 ==> false Wenn wir uns in der jshell den Wert der Variable $17 anzeigen lassen, lernen wir einen dritten Datentyp kennen. jshell> /var $17 | boolean $17 = false Der Typ boolean steht für Wahrheitswerte. Es gibt die beiden Wahrheitswerte true und false: jshell> x < x2 $18 ==> true Wir können auch auf Wahrheitswerten rechnen. Hierzu gibt es drei logische Operationen. Das logische Oder, Disjunktion genannt: jshell> $18 || $17 $19 ==> true 34 Das logische Und, Konjunktion genannt: jshell> $18 && $17 $20 ==> false Und das logische Nicht, Negation genannt: jshell> !$20 $21 ==> true Schließlich kann man auf Grund eines Wahrheitswertes eine Auswahl aus zwei Werten treffen. jshell> $18 ? 900 : -42 $22 ==> 900 Hierzu schreibt man einen bool’schen Ausdruck. Nach diesem ein Fragezeichen. Dann folgen zwei Ausdrücke, die durch einen Doppelpunkt getrennt sind. Der Wert des ge- samten Bedingungsausdruck errechnet sich wie folgt. Erst wird der bool’sche Ausdruck ausgewertet. Ist das Ergebnis true so wird der Ausdruck vor dem Doppelpunkt als Ge- samtergebnis genommen. Ist hingegen das Ergebnis false so wird der Ausdruck nach dem Doppelpunkt als Gesamtergebnis genommen. Da der Wert in der Variablen $18 hier true ist, ist das Ergebnis 900. jshell> $17?900:-42 $23 ==> -42 Da der Wert in der Variablen $18 hier false ist, ist das Ergebnis -42. 1.4.4 Ausdrücke für Zeichenketten Häufig bearbeiten Computerprogramme Texte, die aus Zeichen eines Alphabets bestehen. Solche Zeichenketten lassen sich in Anführungszeichen angeben. jshell> "Es ist noch etwas zu retten" $15 ==> "Es ist noch etwas zu retten" Der Datentyp, den Java hierzu verwendet heißt: String. jshell> /vars | String $15 = "Es ist noch etwas zu retten" 35 Auch auf Daten des Typs String können wir in Java die Operation + durchführen. Dann wird eine neue Zeichenkette errechnet, die die beiden Teilketten aneinanderhängt. jshell> $15+"! Handelt jetzt" $16 ==> "Es ist noch etwas zu retten! Handelt jetzt" Wir können auch eine Zahl mit dieser Operation an einen String anhängen. Dann wird die Zahl textuell als String umgewandelt und anschließend an den anderen String gehängt. jshell> "Das Ergebnis von 17+4*2 ist: "+(17+4*2) $17 ==> "Das Ergebnis von 17+4*2 ist: 25" Ein wenig Vorsicht muss man dabei walten lassen. Betrachten Sie das folgende Beispiel. jshell> "Das Ergebnis von 17+4*2 ist: "+17+4*2 $18 ==> "Das Ergebnis von 17+4*2 ist: 178" Sehen Sie, was hier passiert ist? Anders als einfache Zahlentypen, können wir Sringdaten nach ein paar Eigenschaften fragen. Zum Beispiel einen String nach der Anzahl der darin enthaltenen Buchstaben: jshell> $17.length() $19 ==> 31 Oder man kann für einen String einen neuen String errechnen lassen, der nur noch aus den entsprechenden Großbuchstaben besteht. jshell> $17.toUpperCase() $20 ==> "DAS ERGEBNIS VON 17+4*2 IST: 25" Man kann nach dem Zeichen an einer bestimmten Position in einem String fragen: jshell> $17.charAt(4) $22 ==> 'E' Das Ergebnis ist ein Wert des Datentyps char. jshell> /var $22 | char $22 = 'E' Man kann auch einen neuen String errechnen lassen, indem bestimmte Teile durch andere Teilstrings ersetzt werden. 36 jshell> $17.replaceAll("i","IIIII") $21 ==> "Das ErgebnIIIIIs von 17+4*2 IIIIIst: 25" Man kann explizit einen Teilstring errechnen lassen. jshell> $17.substring(4,10) $23 ==> "Ergebn" Es lässt sich allerhand für einen String errechnen. Wenn Sie in der jshell nach dem Punktsymbol die Tabulaturtaste drücken, dann zeigt Ihnen die jshell an, was Sie alles aus dem String errechnen lassen können. jshell> $17. charAt( chars() codePointAt( codePointBefore( codePointCount( codePoints() compareTo( ,→ compareToIgnoreCase( concat( contains( contentEquals( endsWith( equals( equalsIgnoreCase( getBytes( getChars( getClass() hashCode() indexOf( intern() isBlank() isEmpty() lastIndexOf( length() lines() matches( notify() notifyAll() offsetByCodePoints( regionMatches( repeat( replace( replaceAll( replaceFirst( split( startsWith( strip() stripLeading() stripTrailing() subSequence( substring( toCharArray() toLowerCase( toString() toUpperCase( trim() wait( jshell> 1.4.5 Funktionen Eine der wichtigsten Definitionen in der Mathematik dürfte die Definition des Begriffs Funktion sein. Viele Zweige der Mathematik beschäftigen sich mit nichts anderem als Funktionen und auch Sie haben in Ihrem Curriculum ein Modul, dass sich in der Analysis mit Funktionen beschäftigt. Aus der Schule sollte jeder wissen, was eine Funktion ist. Zum Beispiel die Funktion, die für jede Zahl, das Quadrat der Zahl berechnet: f (x) = x2 Wir wissen schon einmal, dass wir das Quadrat einer Zahl in Java durch die Multiplikation errechnen können. 37 jshell> 1*1 $1 ==> 1 jshell> 2*2 $2 ==> 4 jshell> 3*3 $3 ==> 9 Wir können eine Variable x zu Hilfe nehmen, in der wir erst den Wert speichern, der quadriert werden soll und das Quadrat der Variable x errechnen: jshell> var x=1 x ==> 1 jshell> x*x $4 ==> 1 jshell> x=2 x ==> 2 jshell> x*x $5 ==> 4 jshell> x=3 x ==> 3 jshell> x*x $6 ==> 9 Aber schließlich können wir auch wie in der Mathematik die Quadratfunktion defiineren jshell> int f(int x){return x*x;} | created method f(int) Jetzt gibt es die Funktion mit Namen f 3 und diese kann zum Rechnen für bestimmte Werte verwendet werden: 3 Java sagt nicht Funktion sondern Methode, doch dazu später. 38 jshell> f(1) $7 ==> 1 jshell> f(2) $8 ==> 4 jshell> f(3) $9 ==> 9 jshell> f(-17) $10 ==> 289 jshell> f(17+4*2) $11 ==> 625 In der Funktionsdefinition haben wir angegeben, von welchem Typ der Parameter x sein soll (int x) und von welchem Typ das Ergebnis wein soll (int f). Beides soll eine ganze Zahl sein. Somit ist auch das Ergebnis der Rechnung immer eine ganze Zahl: jshell> /var $11 | int $11 = 625 Die statische Typüberprüfung von Java verhindert, dass wir die Funktion für eine Kom- mazahl anwenden: jshell> f(1.23) | Error: | incompatible types: possible lossy conversion from double to int | f(1.23) | ^--^ 39 2 Grundkonzepte der Objektorientierung Die Grundidee der objektorientierten Programmierung ist, Daten, die zusammen ein größeres zusammenhängendes Objekt beschreiben, zusammenzufassen. Zusätzlich fassen wir mit diesen Daten noch die Programmteile zusammen, die diese Daten manipulieren. Ein Objekt enthält also nicht nur die reinen Daten, die es repräsentiert, sondern auch Programmteile, die Operationen auf diesen Daten durchführen. Insofern wäre vielleicht subjektorientierte Programmierung ein passenderer Ausdruck, denn die Objekte sind nicht passive Daten, die von außen manipuliert werden, sondern enthalten selbst als integralen Bestandteil Methoden, die ihre Daten manipulieren können. 2.1 Interaktive Entwicklung von Klassen Sie erinnern sich an den Java-Interpreter jshell? Bevor wir uns systematisch über Ob- jekte, Klassen und deren Modellierung Gedanken machen, wollen wir diesen etwas spie- lerischen Ansatz nutzen, um eine erste Klasse zu entwickeln. panitz@panitz-ThinkPad-T430:~/gitlab/LectureNotes$ jshell | Welcome to JShell -- Version 11.0.4 | For an introduction type: /help intro Als kleine Beispielsession soll eine Klasse, die Wetterdaten speichert entwickelt werden. Wir beginnen mit einer leeren Klasse: jshell> class Wetter{} | created class Wetter jshell> new Wetter() $2 ==> Wetter@799f7e29 Nun soll diese Klasse ein Feld haben, in dem eine Temperatur in Grad Celsius gespei- chert ist. Statt die neue Version der Klasse in der jshell neu einzugeben, können Sie: /edit Wetter eingeben. Dann geht der Standardeditor mit dem Quelltext der Klasse Wetter auf. Diesen können Sie bearbeiten. Speichern Sie diesen dann, so wird die Klasse mit dieser neuen Version in der jshell geladen. 40 jshell> class Wetter{...> int temperatur;...> } | replaced class Wetter jshell> new Wetter() $4 ==> Wetter@7aec35a Jetzt können wir dem Wetterobjekt einen konkreten Wert im Feld temperatur zuweisen. jshell> $4.temperatur=21 $5 ==> 21 Das in $4 gespeicherte Wetterobjekt hat jetzt den zuvor zugewiesenen Wert. jshell> $4.temperatur $6 ==> 21 Als nächsten Schritt bekommt die Klasse einen Konstruktor. Zum Erzeugen eines Wet- terobjektes ist jetzt ein konkreter Wert für die Temperatur im Konstruktor zu übergeben. jshell> class Wetter{...> int temperatur;...> Wetter(int t){...> temperatur = t;...> }...> } | replaced class Wetter jshell> var w = new Wetter(21); w ==> Wetter@1de0aca6 Das in w gespeicherte Wetterobjekt hat jetzt den im Konstruktor übergebenen Wert. jshell> w.temperatur $9 ==> 21 Als nächstes wird die Klasse um eine Methode erweitert, die die gespeicherte Temperatur in Fahrenheit angibt. 41 jshell> class Wetter{...> int temperatur;...> Wetter(int t){...> temperatur = t;...> }...> double temperaturInFahrenheit(){...> return temperatur * 1.8 + 32;...> }...> } | replaced class Wetter | update replaced variable w, reset to null jshell> var w = new Wetter(21); w ==> Wetter@30946e09 Jetzt können wir ein Wetterobjekt mit einem Methodenaufruf nach der Temperatur in Fahrenheit fragen: jshell> w.temperaturInFahrenheit() $12 ==> 69.80000000000001 natürlich steht weiterhin auch das Feld, in dem die Temperatur in Celsius gespeichert ist, zur Verfügung. jshell> w.temperatur $13 ==> 21 Schließlich soll unsere Klasse noch eine Methode toString enthalten. In dieser soll für die textuelle Darstellung eines Wetterobjektes sowohl die Temperatur in Celsius als auch in Fahrenheit verwendet werden. Hierzu wird innerhalb der Methode toString sowohl auf das Feld temperatur als auch die Methode temperaturInFahrenheit() zugegriffen. 42 jshell> class Wetter{...> int temperatur;...> Wetter(int t){...> temperatur = t;...> }...> double temperaturInFahrenheit(){...> return temperatur * 1.8 + 32;...> }...> public String toString(){...> return "Es sind "+temperatur+" Grad Celsius, "...> +"das entspricht "+temperaturInFahrenheit()...> +" Grad Fahrenheit.";...> }...> } | replaced class Wetter | update replaced variable w, reset to null Die jshell verwendet jetzt automatisch die toString-Methode bei der Anzeige eines Wet- terobjektes. jshell> var w = new Wetter(21); w ==> Es sind 21 Grad Celsius, das entspricht 69.80000000000001 Grad ,→ Fahren Am Ende einer solchen interaktiven Session zur Entwicklung einer Klasse, können wir diese mit der jshell-Anweisung /save in eine Javaquelltextdatei abspeichern. jshell> /save Wetter Wetter.java Wem das zu schnell war, für den gehen wir in den nächsten Abschnitten der Entwicklung von Klassen etwas systematischer nach. 2.2 Objektorientierte Modellierung Jetzt wollen wir erst einmal eine informelle Modellierung der Welt, für die ein Programm geschrieben werden soll, vornehmen. Hierzu empfiehlt es sich durchaus, in einem Team zusammenzusitzen und auf Karteikarten aufzuschreiben, was es denn für Objekte in der Welt gibt, die wir modellieren wollen. Stellen wir uns hierzu einmal vor, wir sollen ein Programm zur Bibliotheksverwaltung schreiben. Jetzt überlegen wir einmal, was gibt es denn für Objektarten, die alle zu den Vorgängen in einer Bibliothek gehören. Hierzu fällt uns vielleicht folgende Liste ein: Personen, die Bücher ausleihen wollen. 43 Bücher, die ausgeliehen werden können. Tatsächliche Ausleihvorgänge, die ausdrücken, dass ein Buch bis zu einem bestimm- ten Zeitpunkt von jemanden ausgeliehen wurde. Termine, also Objekte, die ein bestimmtes Datum kennzeichnen. Nachdem wir uns auf diese vier für unsere Anwendung wichtigen Objektarten geeinigt haben, nehmen wir vier Karteikarten und schreiben jeweils eine der Objektarten als Überschrift auf diese Karteikarten. Jetzt haben wir also Objektarten identifiziert. Im nächsten Schritt ist zu überlegen, was für Eigenschaften diese Objekte haben. Beginnen wir mit der Karteikarte, auf der wir als Überschrift Person geschrieben haben. Was interessiert uns an Eigenschaften einer Person? Wahrscheinlich ihr Name mit Vorname, Straße und Ort sowie Postleitzahl. Das sollten die Eigenschaften einer Person sein, die für ein Bibliotheksprogramm notwendig sind. Andere mögliche Eigenschaften wie Geschlecht, Alter, Beruf oder ähnliches inter- essieren uns in diesem Kontext nicht. Jetzt schreiben wir die Eigenschaften, die uns von einer Person interessieren, auf die Karteikarte mit der Überschrift Person. Schließlich müssen wir uns Gedanken darüber machen, was diese Eigenschaften eigentlich für Daten sind. Name, Vorname, Straße und Wohnort sind sicherlich als Texte abzuspei- chern oder, wie der Informatiker gerne sagt, als Zeichenketten. Die Postleitzahl ist hin- gegen als eine Zahl abzuspeichern. Diese Art, von der die einzelnen Eigenschaften sind, nennen wir ihren Typ. Wir schreiben auf die Karteikarte für die Objektart Person hinter jede der Eigenschaften noch den Typ, den diese Eigenschaft hat. Damit erhalten wir für die Objektart Person die in Abbildung 2.1 gezeigte Karteikarte. Abbildung 2.1: Modellierung einer Person. 44 Gleiches können wir für die Objektart Buch und für die Objektart Datum machen. Wir erhalten dann die Karteikarten aus Abbildung 2.2 und 2.3. Abbildung 2.2: Modellierung eines Buches. Abbildung 2.3: Modellierung eines Datums. Wir müssen uns schließlich nur noch um die Objektart einer Buchausleihe kümmern. Hier sind drei Eigenschaften interessant: wer hat das Buch geliehen, welches Buch wurde verliehen und wann muss es zurückgegeben werden. Wir können also drei Eigenschaften auf die Karteikarte schreiben. Was sind die Typen dieser drei Eigenschaften? Diesmal sind es keine Zahlen oder Zeichenketten, sondern Objekte der anderen drei bereits modellierten Objektarten. Wenn wir nämlich eine Karteikarte schreiben, dann erfinden wir gerade einen neuen Typ, den wir für die Eigenschaften anderer Karteikarten benutzen können. Somit erstellen wir eine Karteikarte für den Objekttyp Ausleihe, wie sie in Abbildung 2.4 zu sehen ist. 45 Abbildung 2.4: Modellierung eines Ausleihvorgangs. 2.3 Klassen und Objekte Wir haben in einem Modellierungsschritt im letzten Abschnitt verschiedene Objektar- ten identifiziert und ihre Eigenschaften spezifiziert. Dazu haben wir vier Karteikarten geschrieben. Jetzt können wir versuchen, diese Modellierung in Java umzusetzen. In Ja- va beschreibt eine Klasse eine Menge von Objekten gleicher Art. Damit entspricht eine Klasse einer der Karteikarten in unserer Modellierung. Die Klassendefinition ist eine Be- schreibung der möglichen Objekte. In ihr ist definiert, was für Daten zu den Objekten gehören. Zusätzlich können wir in einer Klasse noch schreiben, welche Operationen auf diesen Daten angewendet werden können. Klassendefinitionen sind die eigentlichen Pro- grammtexte, die der Programmierer schreibt. Merken Sie sich: In Java steht genau eine Klassendefinitiona in genau einer Datei. Die Datei hat dabei den Namen der Klasse mit der Endung.java. a Auch hier werden wir Ausnahmen

Use Quizgecko on...
Browser
Browser