4, 3, 2, 1, juhu.
Herzlich willkommen zur sechsten Vorlesung, Softwareentwicklung 1 im Wintersemester 15
, 16. So, dass dieses Semester ist,
sehen Sie auch an diesem recht aktuellen Bildschirmabzug.
Ich bin von Christian Spee und Fred gebeten worden,
wie nochmal darauf nicht nochmal,
aber Sie auch im Rahmen der Vorlesung darauf hinzuweisen,
wir haben ein Tutorium.
Dieses Tutorium findet immer am Freitag von 14.15 Uhr
bis 15.45 Uhr
In diesem Raum am Informatikum statt und diejenigen von ihnen,
die da hingehen möchten,
weil Fred und ich und die Übungsgruppenleiter es nicht geschafft haben,
ihnen das Zeug so nahezulegen, dass sie beruhigt ins Wochenende gehen können,
mögen sich im Vorfeld dann überlegen,
was sie für Fragen an den anwesenden Tutor stellen wollen.
So, jetzt bin ich diese Einladung losgeworden und wenn am
Freitag 500 von ihnen im D018 sind, weiß ich,
dass die Einladung erfolgreich war.
Das wird eng
Ja. Ja, das kreuzt auch aus.
Hauptsächlich der Maske war ja, es ist immer so.
Das Tutorium aufzeichnen lassen. Das war ja Smaske.
Ich gebe diese Frage hiermit an den Anwesenden Lecture-to-Go-Kollegen weiter,
dass der Wunsch nach Aufzeichnung des Tutoriums
an mich herangetragen wurde
Und damit ist dieses Thema für mich jetzt auch erledigt.
Also wenn ihr was wisst, dann sagt es mir,
dann sage ich nächste Woche, geht klar oder geht nicht klar.
Okay. So, jetzt aber, jetzt im Sause-Schritt,
sechste Vorlesung, objektorientierte Grundlagen, objektorientierter Programmierung. Heute werden wir uns,
werden wir in Fortsetzung dessen,
womit wir uns letzte Woche Mittwoch beschäftigt haben,
nämlich mit dem Typkonzept, werden wir das nochmal kurz,
also wir werden das nochmal kurz aufbereiten, worüber wir gesprochen haben,
um dann sogenannte Benutzer definierte Typen einzuführen und die Möglichkeiten,
die sich durch dieses Konzept ergeben, die werden wir dann besprechen.
So, wir haben, letzte Woche haben wir
über die sogenannten elementaren Datentypen gesprochen. Wie gesagt,
das werde ich jetzt gleich nochmal kurz wiederholen, um numerische,
logische Problemstellungen zu lösen, dass das nicht alles ist,
können sie
sich denken
Als worum es dann heute im Wesentlichen geht,
sind also die schon hier hinterlegten oder hervorgehobenen Benutzer definierten Klassen,
die es uns erlauben auf Basis dieses Typsystems,
auf Basis des Typsystems, objektorientierter Programmiersprachen,
auch selbst definierte Typen in objektorientierten Programmen sicher zu verwenden.
Zurück, also vielleicht nicht, bevor ich zurückgehe,
hier jetzt mal die Definition für einen Datentypen,
so wie sie aus dem Informatik-Duden entnommen worden ist.
Also die Zusammenfassung, ein Datentyp ist die Zusammenfassung von,
Bereichen und Operationen zu einer Einheit. Das haben wir da so lange drüber gesprochen,
was das so am Beispiel, also der Integers beziehungsweise der Buliens, was das bedeutet.
Bei den Zahlen haben wir noch über andere Datentypen gesprochen. Wichtig ist jetzt hier für den Moment einfach nur,
das heißt einfach nur wichtig ist für den Moment,
also immer mal wieder festzuhalten,
also so ein Typ in einer statisch getypten Programmiersprache bedeutet,
ich habe einen Wertebereich und es gibt bestimmte Operationen,
die ich auf diesem Wertebereich ausführen kann und wenn ich eine Operation auf einem Wertebereich versuche auszuführen,
die dafür nicht definiert worden ist, dann habe ich keine Chance,
dieses Programm jeweils zum Laufen zu bringen,
weil der Compiler keinen ausführbaren Code erzeugen wird.
Damit sind wir also absolut auf der sicheren Seite. Das ist,
was da nämlich stattfindet zur Compile-Zeit,
ist die sogenannte Prüfung und zur Kompile-Zeit, deswegen heißt es auch,
also die statische Typ-Prüfung und das ist bei,
hatten wir auch schon kurz drüber gesprochen,
das ist bei denen bei vielen,
also heute weit verbreiteten, objektorientierten Programmiersprachen,
ist,
dass der Standard,
es gibt eine statische Typ-Prüfung
Und deswegen können sie in ihrem Programm, können sie so Zeilen hinschreiben,
wie das, was hier in der ersten Beispielzeile steht,
diese Operationen können sie ausführen,
12 und 6 sind bekannte Literale für Intager,
die Operation plus ist als Infix-Operation,
das haben wir beim letzten Mal auch besprochen,
was es so für Aussagen über Operatoren gibt.
Der Compiler kann das als eine korrekte Anweisung,
als einen korrekten Ausdruck verstehen und der Intager variable Zoom einen entsprechenden Wert zuweisen.
Das macht natürlich nicht der Compiler, der Compiler stellt fest,
dass er ausführbare Code herstellen kann und zur Laufzeit wird dann der variable Zoom dieser Wert zugewiesen.
Derselbe Compiler kann auch feststellen, Das ist also keinen Sinn,
ergibt zwölf mit dem Bullshen-Literal-Fords in Verbindung zu bringen,
zu wollen und das auch noch mit dem Operator plus,
weil der Operator plus ist eben nur für Intager und vergleichbare Typen definiert, aber nicht für Bulien.
Und deswegen wird es, also wenn Sie versuchen,
diese Zeile zu übersetzen, zu einem Typfehler, zu einem Typfehler führen.
Der Compiler wird Ihnen das also mitteilen. Weil wir haben uns letzte Woche dann auch angeschaut,
also so in diesem Video vor, also diejenigen von Ihnen,
die so um zwei Uhr da waren, wir haben uns angeschaut,
was passiert in einer nicht statisch getypten Programmiersprache,
welche Effekte das hervorrufen kann
So mehr oder weniger lustig im Alltag, im Beruf,
im beruflichen Alltag, ist es eigentlich weniger lustig.
Sie sehen das hier, dass es also durchaus eine Klasse von Ernst und Ernst
wirklich, nicht das Java-Skript, keine ernstzunehmende Programmiersprache wäre.
Also ganz im Gegenteil. Aber die Probleme,
die sich bei der Verwendung nicht staatisch typisierter programmiersprachen, ergeben,
müssen halt immer abgewogen werden mit den Möglichkeiten, die sich gleichzeitig ergeben.
Und hier ist als Beispiel für eine nicht statisch getypte Programmiersprache
ist hier Smalltalk angegeben. Smalltalk ist so eine der,
wenn man so will, einer der Urmütter, der Objektorientierung,
Programmiersprachen ist schon in den 80er Jahren des letzten Jahrhunderts weit verbreitet gewesen.
Da könnten sie so eine Anweisung hinschreiben, was auch immer
sie dazu bewegt, also diese Anweisung zu formulieren.
Und das würde eben erst in dem Moment, wo versucht wird,
diesem Code auszuführen, würde es zu einer Fehlermeldung kommen,
weil erst dann klar wird,
dass diese Nachricht also nicht interpretierbar ist.
So, das also so zu Typ Prüfung, Elementaren,
Datentypen, statischer Typ Prüfung.
Jetzt noch ein ganz kurzer Blick in die Historie
So, am Ende des Tages ist das ja auch immer noch,
also, dass das, was da im Hauptspeicher stattfindet,
sich alles auf der Ebene von Nullen und Einsen abspielt.
Und gut, Fred hat ihn ja letzte Woche schon so in,
schon so das eine oder andere Beispiel dazu gezeigt,
wie man also auch mit Java-Operationen quasi, also mindestens die Illusion bekommt,
direkt in den Hauptspeicher reinschauen zu können, also auf Bit-Ebene, Operationen durchführen zu können.
Und das Modell, das ich, wir versuchen ihn zu vermitteln,
ist ja Nun so eine Java-Programmierumgebung ist jetzt,
also so weit wie die Programmiersprache,
ihnen die Mittel zur Verfügung stellt, schon eine Abstraktion über dem,
was da unten im Hauptspeicher eigentlich passiert, mal,
weil ganz abgesehen davon,
dass wir es in irgendeiner Form mit Strom von in irgendeiner Form von oder mit Strom zu tun haben,
das interessiert uns eigentlich.
Davon können wir so weit abstrahieren, also wie nur möglich,
ob das Ding mit Feuer betrieben wird oder mit Strom ist uns eigentlich egal.
Die Ebene, auf der wir es,
also mit in einer Programmiersprache zu tun haben,
ist die Ebene der elementaren Typen
Und die sind eine Abstraktion von dem Hauptspeicher. Und jetzt gehen wir im weiteren Verlauf,
machen wir einen weiteren oder wir versuchen mindestens einen weiteren Abstraktionsschritt,
dass wir uns nämlich von dieser hier metaphorisch als leicht bekleidet
bezeichneten Ebene hin zu einer voll angezogenen,
vollbekleideten Ebene zu bewegen.
Wir möchten weitere Abstraktionsebenen zwischen uns vollbekleidet und dem Hauptspeicher,
in dem es sich auf der Ebene abspielt,
einziehen können
Weil wir so, wenn wir über Anwendungsprogramme sprechen, also über das,
womit wir uns jetzt eigentlich bei der Entwicklung von Software beschäftigen,
die Welt besteht nicht aus Intelligence. Also ich meine,
sie besteht sowieso nicht aus Integern, Flowds, Buliens,
aber die Art und Weise,
wie wir über die Lösung von Softwareproblemen in der Anwendungswelt nachdenken wollen,
soll auch nicht auf der Ebene von diesen elementaren Datentypen stattfinden,
sondern wir wollen Benutzer definierte Datentypen verwenden,
um die Probleme der Alltagswelt, also in Software,
also teilweise, um Problemstellung, ich soll es jetzt so formulieren.
Um Problemstellung aus der Alltagswelt, mit Software lösen zu können.
Man könnte das jetzt, so der Begriff,
der dafür häufig verwendet wird, um dieses Problem zu bezeichnen,
ist die sogenannte semantische Lücke.
Die Semantic Gap, die besteht darin,
hier ist der Hauptspeicher oder von mir aus die elementare Datentypen,
die einem eine Programmiersprache zur Verfügung stellen.
Und hier sind die Probleme der Anwendungswelt.
Die Probleme der Anwendungswelt sind von der Art,
ich möchte ein Konto eröffnen
Ja, was fällt mir schon ein Problem in der Anwendungswelt
ein? Außer, dass ich ein Konto eröffnen möchte.
So, aber diese Lücke ist vergleichsweise groß. Zumal,
wenn ich also hier nur so ein paar Intagers zur Verfügung habe und Buliens,
dass sie mit denen nicht dieses Problem formulieren kann.
Und jetzt wäre es doch hübsch,
wenn wir diese Ebene hier der Maschinen, der maschinellen Datenverarbeitung,
wenn wir die so der Welt der Anwendung ein klein wenig näher bringen können.
So, weil eins der Probleme,
mit dem sie sich dann ja auch im Berufsleben beschäftigen werden müssen,
ist, die Welt da draußen verändert sich ständig.
Neue Gesetze, kommen werden verabschiedet. Es gibt neue Technologien
und hier ist die Software, die sie geschrieben haben.
Und wenn sie die Software,
an die sich verändernde Welt oder auch an sich verändernde Anforderungen anpassen wollen,
dann müssen sie da einen Bezug herstellen zwischen den Problemstellungen der Anwendungswelt und dem,
was sie in Software formuliert haben.
So, und je größer die Lücke ist,
desto schwerer wird ihnen das fallen. Und deswegen wollen wir
diese Lücke so klein machen wie möglich und ein Element,
um diese Lücke zu verkleinern,
sind diese sogenannten Benutzer definierten Typen
So, um solche Benutzer definierten Typen in die Welt der Programmiersprachen
zu bringen, gibt es zwei Ansätze. Sie sehen hier,
Sie sehen die so ein bisschen gegenübergestellt, als einmal der Ansatz,
der zum Beispiel durch eine Programmiersprache wie PL1, Programming,
Langwitch One in der Langform realisiert worden ist.
Man hat versucht, also mit dieser Sprache Anwendungsdefinierte Typen,
ich bleibe mal beim Konto oder beim Vertrag, Antrag,
irgendwas, von der er kannte.
Man hat versucht, das Indie-Programmiersprache einzubauen
Sagen. So, es gibt nicht nur Integers und Boolions,
sondern es gibt auch ein Konto. Okay. Ich finde
die Idee erstmal absolut nachvollziehbar. Oder man könnte auch sagen,
ein Formular, so Frei nach Tucholski,
von der Wiege bis zur Barre, Formulare, Formulare.
Also warum nicht ein Formular in eine anständige in Deutschland verwendete Programmiersprache einbaut?
So, dann machen wir das. Es hat sich dann herausgestellt,
ja, die einen möchten so ein Formular haben und die anderen möchten so ein Formular haben.
Und es wird vergleichsweise schnell unübersichtlich. Es lässt sich für
eine kleine Menge von Problemstellungen lässt sich das auch machen.
Im Großen und Ganzen hat sich das also mindestens bis heute als Ansatz nicht durchgesetzt.
Es gibt jetzt neuere Ansätze, die sogenannten Domain Specific Languages. Kurz DSLs,
die diesen Ansatz wieder aufgreifen und die Idee ist dabei,
wir nehmen uns einen kleinen Ausschnitt aus einer Problemlandschaft und modellieren
die Programmiersprachlichen Elemente sehr nahe an den Problemen, die gelöst werden sollen.
So, diese DSLs sind so im Bereich der Implementierung reaktiver Systeme,
also technische Systeme, die sich schon vergleichsweise weit durchgesetzt.
Und im Moment schauen so einige in die Richtung.
Wir möchten zum Beispiel spezialisierte Formen von Excel, also für die Konfiguration von Automobilen,
der sich damit mal beschäftigt hat, das ist ein Albtraum,
für die Konfiguration von Albtraum aus dem Immobilien zur Verfügung stellen.
Also dieser Ansatz, der vordeklarierten Datentypen in Programmiersprachen,
der ist nicht tot, die leben die Todgesagten,
leben ja im Übrigen auch länger,
sondern das wird sie in anderen der Veranstaltung im Bachelor,
wahrscheinlich sogar im Masterstudium, wird ihnen das nochmal begegnen.
Der Ansatz, mit dem wir uns hier beschäftigen,
ist der Ansatz, der auch in Java verwendet wird.
Dieser Ansatz ist zuerst in Programmiersprachen wie Algor 60 oder Allgord 68,
also es 60, 68 steht jeweils für Jahreszahlen,
ist der realisiert worden. Dieser Allgord steht für Algorithmic Language,
das waren so die ersten Programmiersprachen, die Informatiker entwickelt haben,
so eine Programmiersprache der sogenannten dritten Generation,
wo genau diese Abstraktionsebene der elementaren Datentypen in die Programmiersprache eingezogen worden ist.
Der Ansatz dieser Programmiersprachen besteht darin, dass ein kleiner Satz von,
so orthogonalen, da sind wir wieder bei orthogonal, so letzte Woche.
Sie erinnern sich, Purpoint Dicula. Von orthogonalen Elementen in
die Programmiersprache eingebaut wird. Und diese Konstruktionselemente sollen von ihnen
den Experten dazu verwendet werden, ohne Benutzer definierte Typen zu konstruieren.
So nach dem Motto, wir geben euch mit den Mitteln der Programmiersprache,
das in die Hand, was ihr braucht,
um Benutzer definierte Datentypen zu definieren.
Benutzer definierte Datentypen implementieren, sollte ich sagen. So,
und das gucken wir uns jetzt mal an,
wie das in Java geht und Java dann stellvertretend für eine moderne objektorientierte Programmiersprache.
Um das tun zu können, müssen wir noch einen Blick zurückwerfen auf das,
was Sie jetzt schon kennengelernt haben, beim Umgang mit den Imperativen Variablen.
So, da haben Sie sich bisher keine Gedanken drüber gemacht,
vermute ich jedenfalls, war auch nicht notwendig,
weil so das Prinzip ist sehr imperativen Wertvariablen,
ist intuitiv nachvollziehbar.
Das geht so
Sie deklarieren eine variable mit dem Bezeichner Antwort. Und die ist vom Typ Integer
. Soweit so gut. Nichts Neues. Das Modell,
das ich Ihnen jetzt nahelege, sagt,
nun stellen Sie sich bitte gleichzeitig vor,
wenn Sie das hinschreiben, dann bedeutet das,
dass irgendwo in diesem Hauptspeicher wird also so viel Speicherplatz reserviert,
dass genau ein Integer da reinpasst.
Den dürfen Sie verwenden nach Ihrer Wahl,
also im Programm
Und dann dürfen sie auch sowas schreiben, wie Antwort wird zu 42.
Dann weiß das Laufzeitsystem sofort, aha,
ich soll also nur an den Platz im Hauptspeicher,
der für diese Variable vom Typ Integer reserviert worden ist,
soll ich jetzt den Wert 42 reinschreiben.
Gesagt, getan. Die Geschichte ist erzählt. Jetzt kommt
was, jetzt kommt, wird dieses Modell etwas erweitern.
Und das ist das Modell, das für die im sogenannten
imperativen Referenzvariablen gilt. Und dieses Konzept brauchen wir,
um die Benutzerdefinierten, Datentypen zu verstehen.
Das geht so
Wir haben jetzt auf einmal, wir haben es auf einmal
mit zwei Elementen im Hauptspeicher zu tun. Und dieses,
ich mache das auch gleich an, ich werde das versuchen,
am Beispiel noch etwas deutlicher zu machen und Fred wird ihnen die Effekte,
oder die wilden Mechanismen,
dieses Prinzips der Referenzvariablen dann auch in Java nochmal klarmachen.
Und am Freitag im Tutorium können sie das nochmal sich anhören.
Wenn sie eine Referenzvariablen deklarieren,
dann deklarieren sie eine Variable, deren Aufgabe es ist,
eine Referenz, einen Verweis einzureferenzierendes Objekt zu halten.
Und dieses Objekt ist dann eins von Ihnen definierter Benutzer definierter Typ
oder eine von Ihnen oder dieses Objekt ist ein Exemplar,
einer von Ihnen geschriebenen Klasse.
Warum das Synonym ist, komme ich gleich noch da drauf.
Das heißt, es ist nicht nur so,
wie wir das bisher kennengelernt haben, Sie deklarieren eine variable,
eine imperative Variable vom Typ Intenter und die hat einen Wert und einen Bezeichner.
Und wenn eine Zuweisung stattfindet, dann steht dieser Wert,
in dem Stück Speicher. Nein, hier müssen wir uns
jetzt über zwei Elemente müssen wir uns im Klaren sein,
wenn wir über Benutzer definierte Datentypen sprechen.
So, jetzt vermute ich mal, ist das ein oder
andere Fragezeichen. Ist jetzt bei Ihnen im Kopf aufgetaucht?
Deswegen jetzt hier gleich das Beispiel dazu, um das hoffentlich
ein bisschen klarer zu machen. Wir deklarieren jetzt also,
zunächst mal haben wir irgendwo eine Klasse Konto geschrieben.
Das können Sie. Das glaube ich, dass Sie das können.
Und dann können Sie an einer anderen Stelle in einer anderen Klasse,
können Sie jetzt eine Variable vom Typ Konto deklarieren?
Die mag dann mal
ein Konto heißen
So, was jetzt passiert ist, sagt wieder der Compiler,
aha, ich soll jetzt also Speicherplatz für eine Reffe offensichtlich eine Referenzvariable deklarieren,
weil so ein Konto ist ja etwas,
das haben Sie geschrieben, es ist ein selbstdefinierter Typ,
dann mache ich das mal.
Und Marvin deklariere ich hier genau so viel Speicherplatz, wie es braucht,
um eine Variable des Typs Kontos, also zu deklarieren.
Das ist dieser Speicherplatz. Soweit ist das alles vergleichbar mit
dem, was auch bei den elementaren Datentypen passiert.
Jetzt kommt aber die Ihnen auch nicht unbekannte Anweisung,
Nämlich, ich weise an die Variable ein Konto,
ein Objekt der Klassekonto, das ich mit dieser Anweisung erzeuge, zu.
Und jetzt wird folgend, jetzt passiert folgendes.
Für sie wird jetzt an diese hier deklarierte Variable eine Referenz
zugewiesen für ein dynamisch erzeugtes Objekt von der Klasse Konto.
So, das haben wir jetzt hier mal so grafisch veranschaulicht.
Das ist das Modell, das sie jetzt im Kopf haben sollten,
wenn sie Objekte von Benutzer definierten Datentypen deklarieren
Es finden, es werden zwei Arken von Speicherplatz werden dafür benötigen.
Einmal der Platz, um die Referenzvariabe zu verwalten und dann
noch der Speicherplatz über dessen Allokationen sie sich keine Gedanken machen müssen.
Also alles, was hier passiert,
passiert also im Hintergrund und wird durch das Laufzeitsystem erledigt.
Das Laufzeitsystem erzeugt ein Objekt von der Klasse Konto und sie können
dieses Objekt erreichen über die von ihnen deklarierte Variable Referenzvariable in unserem Fall mit dem Bezeichner ein Konto.
Dieses Ding hier hat keinen Namen, also das können sie erreichen über diese Referenz variable. So,
ich werde im späteren Verlauf auf noch was dazu sagen,
was dieser für den Moment Bubbel, was der bedeutet,
weil das ist so, wenn ich das so kurz erzählen darf,
das ist eine, da komme ich dann im weiteren Verlauf auch noch zu,
das ist schon ein Element aus einer Notation namens UML,
Unified Modeling Language.
Und wenn Sie in Ihrem weiteren Verlauf,
in dem weiteren Verlauf Ihrer studentischen wissenschaftlichen Berufskarriere,
wenn Sie Lotationen verwenden,
eins sage ich
Ihnen gleich
Verwenden Sie bekannte Notationen, Standardnotationen, nicht irgendwelche Freistehenotationen,
weil Sie möchten nicht in der Situation sein,
in der ich mich regelmäßig befunden habe,
wenn ich Vorträge damals vor meiner Doktormutter gehalten habe.
Ich habe irgendeine Zeichnung dahingelegt und die brauchte sich über die
überhaupt nicht inhaltlich mit dem auseinandersetzen, was ich ausdrücken wollte,
weil die Killerfrage war immer, Guido, was bedeuten die Pfeile?
Wenn ich dann als Antwort nichts anderes hatte,
als hängt irgendwie zusammen mit, war das eine unwissenschaftliche, nicht hinreichende Antwort.
Also sagen Sie, das ist ein UML-Objektdiagramm. Und damit
machen Sie es dann zum Problem desjenigen, der Ihnen zuhört.
Weil das muss erkennen oder die. Oder das nicht kennt.
Also wenn er sich mal sachkundig macht, bevor er Ihnen zuhört.
Das nur, weil so als Tipp für Ihre Vorträge im weiteren Verlauf Ihres Studiums.
So, zurück zum Thema Referenztypen sind Typen. Aha,
was bedeutet das? Nun, für Typen hatten wir festgelegt,
Wertebereich und Operationen, die darauf ausgeführt werden können.
Und das können wir jetzt hier so zusammenfassen,
Was sind denn die Elemente eines Referenztyps?
Na, das sind die Exemplare der definierenden Klasse.
Also die ist nicht im Vorhinein bestimmt, wie das bei den Bildern,
das bei den elementaren Typen der Fall gewesen ist.
Also die Literale kann man ja alle aufschreiben oder auch nicht.
Also im Vergleich, wenn man mal, kann man alle Floats aufschreiben?
Kann man. Also irgendwas kann man darauf nicht aufschreiben.
Das sind keine Chancen. Aha, es gibt keine Shortliterale,
höre ich gerade. Es ist zwar, glaube ich,
ich wollte auf etwas anderes eben mathematische Sinne überabzählbar unendlich
auf sowas hinaus, aber das ist nochmal ein anderes Thema
Die können die Elemente eines Referenztypen nicht also aufzählen,
weil die Objekte, die Exemplare werden ja dynamisch erzeugt.
Also es steht ja hier auch nochmal beliebig viele Exemplare einer Klasse
können erzeugt werden. Das sollten Sie sich auch merken,
es gibt also immer mal wieder taucht das Gerücht auf,
dass also die Anzahl der Exemplare einer Klasse in irgendeiner Form beschränkt ist.
Also wenn man das mal in der Klausur fragt,
also wie viele Exemplare der Klasse Konto können erzeugt werden und
die Antwortmöglichkeiten ist 1,42 unendlich viele.
Das ist, also ich will nicht sagen gewürfelt an vielen Stellen,
aber überraschend enttäuschend oft wird die Anzahl 1 angekreuzt
Also das ist falsch. Können sie sich jetzt schon merken
. Diese Frage werden wir wahrscheinlich nicht widerstellen. So,
die Operationen, die auf einem Referenztypen ausgeführt werden können,
na, das sind sie, die das entscheiden,
welche Operationen das sind.
Und das ist also diese Entscheidung, ist also unmittelbar davon abhängig,
welche Operationen sie an einem Referenztypen aufgerufen haben können möchten.
So, das sind nämlich genau das, ist genau das,
was sie bisher als Public Operation kennengelernt haben.
Das, was von außen hin sichtbar ist. So,
zusammengefasst in der Notation, in der wir das schon für
die anderen für die elementaren Datentypen kennengelernt haben.
Sie definieren, die einen Datentyp,
in dem sie eine klasse schreiben, welche Wertemenge hat der?
Naja, alle Objekte, die davon erzeugt werden können.
Also die Menge der Kontoexemplare, welche Operationen stehen bei diesen Datentypen zur Verfügung,
die Operationen, die Methoden, die sie als Public deklariert haben.
Damit haben wir also jetzt ein vergleichbares Instrumentarium zur Beurteilung
sowohl von elementaren Datentypen als auch von Benutzer definierten Datentypen,
sprich den Referenztypen geschaffen
So, jetzt können wir das noch zusammenbringen mit einem Begriff,
den wir an anderer Stelle auch schon kennengelernt haben,
nämlich den Begriff der Schnittstelle.
Und Sie sehen hier dieses große Gleichheitszeichen,
das kennen Sie ja mittlerweile auch schon, aus der Java-Notation,
dass die Operationen eines Referenztyps sind gleich der Schnittstelle der definierenden Klasse.
Und in diesem Sinne ist also, ist das Synonym. Das heißt also,
da gibt es eigentlich keinen Unterschied und das könnte man dann auch,
also im Sinne von Bertrank Meyer,
könnte man sagen,
klasse ist gleich Typ
Das haben wir jetzt also geschafft, gut,
in einer knappen halben Stunde, diesen Zusammenhang auch herzustellen.
Wie schön. So, ein Problem,
jetzt können Sie also beliebige Benutzer definierte Typen,
können Sie schaffen, ein Problem,
dass Ihnen im Laufe Ihrer Programmierpraxis also bestimmt häufiger begegnen wird,
ist das sogenannte Alias-Problem. Dieses alias-Problem, glaube ich,
werden wir auch so an der einen oder anderen Stelle heute noch thematisieren,
wenn ich mich beeile, dreht das vielleicht noch hin,
schauen wir mal, also dieses alias-Problem, worin besteht das?
Wir stellen uns jetzt mal vor, Das hier sei das Objekt
der Klasse, aha. Und dieses Objekt der Klasse,
aha, enthält eine Referenz auf ein Objekt der Klasse C.
Und die, und das Objekt der Klasse B enthalte,
auch eine Off-Kreeferenz auf das Objekt der Klasse C.
So, das heißt also jetzt erst mal auf Deutsch gesagt,
dass sowohl A als auf B auf dasselbe Objekt referenzieren.
So, und jetzt kommt ein Punkt,
also da haben sie es als zukünftige Experten, Softwareentwickler,
Sie, wir machen sie jetzt, also vertraut mit einem Problem,
dass alle haben, bloß wovon die anderen nicht wissen,
dass sie es haben.
Das ist das Problem des One-Off, das redet ja
auch schon an einer anderen Stelle hier beschrieben hat.
Umgangssprachlich werden die Worte, dasselbe und das Gleiche häufig miteinander
vermischt und es macht auch keinen Unterschied. Also jedenfalls im Alltag. So,
wenn sie irgendwo in der Kneipe sitzen und der eine sagt,
ein Bier bitte und der Kellner fragt sie,
möchten sie und sie sagen, dasselbe ist es genauso gut,
als wenn sie sagen, das Gleiche.
Es kann passieren, dass ihr Gegenüber sprachlich vielleicht,
also ein bisschen versnobter ist. Ich weiß gar nicht,
wie ich das ausdrücken soll. Und dann sagt er,
wenn sie sagen, dasselbe, dann sagt er, nein,
das möchtest du nicht, du möchtest höchstens das Gleiche haben.
Weil sie wollen sich dasselbe Bier wie ihr Gegenüber trinken.
Höchstens, wenn es zwei Strohhalme gibt.
Das ist aber wieder
was anderes
Während man, so man könnte sich jetzt darauf einlassen und sagt,
wenn ich sage, ich möchte dasselbe,
dann spreche ich von der Art und nicht von dem Exemplar.
Also nicht von dem Typ, sondern von dem,
nicht von dem Objekt, sondern von dem Typ.
Sie sehen, man kann als Informatiker auch im Alltag,
da kann man sich viel Ärger reiten.
Worauf ich hinaus möchte, das alias Problem besteht darin,
dass die Objekte A und B dasselbe Objekt referenzieren.
Und jetzt kann Folgendes passieren vom Objekt A
Rufen Sie die Operation Sätze auf, was auch immer die jetzt setzt.
Die verändert auf jeden Fall den Zustand des Objektes C.
Das Objekt B bekommt davon nichts mit. Wenn dieses Objekt B jetzt sagt,
gib X oder gib Y, dann befinden sich die,
dann ist dieses Objekt C zwischenzeitlich in einen anderen Zustand versetzt worden.
Und das ist ein Problem, Wovon man sich jetzt
so sagt, so warum kreieren die sich überhaupt?
Also Möglichkeiten, die es erlauben, also so ein Problem herzustellen.
Das ist ja eine Katastrophe. Nun,
jetzt habe ich Ihnen erst mal gesagt,
was das Problem ist und Freds Aufgabe wird es eh sein,
Ihnen die Möglichkeiten des Umgangs mit Referenzvariablen darzustellen.
Ich wollte jetzt erst mal nur sagen,
dass alias Problem ist ein Problem, mit dem wir uns,
also so an der einen oder anderen Stelle im Programmieralltag beschäftigen werden müssen.
So, und jetzt komme ich in den letzten Minuten noch
kurz zu der UML, Unified Modernin Language, Modeling Language.
Ich hatte das schon angesprochen, das ist eine Notation,
die ist mittlerweile Standard
In der Notation für Problemstellungen, die sich bei der Modellierung, objektorientierter Anwendungssysteme ergeben. So, die drei Buchstaben UML habe ich schon erläutert. Diese UML,
die UML ist entstanden, ein kurzer Blick in die Geschichte,
so bevor es die UML gab,
gab es also eine Menge von konkurrierenden Rotationen und das hat also immer den Effekt gehabt,
also wenn Leute über Grafiken versucht haben, sich ein Problem zum Vergegenständlichen,
dass die Frage war, das, was ich Ihnen gerade schon sagte,
was bedeuten die Pfeile, was bedeuten die Kästen,
das bedeuten die runden Ecken, so das kostet einfach Zeit, also bis man sich und nerven.
Also wenn es nicht klar ist, was in so einer Grafik eigentlich bedeutet. So,
und dann hat man ein paar Jahre für gebraucht,
bis sich also die Protagonisten der jeweiligen Methoden sich darüber einig geworden sind,
welche Methode man denn jetzt eigentlich,
welche Notation man jetzt eigentlich verwenden sollte und die UML ist das Ergebnis,
sie sehen hier, also auch den entsprechenden Link,
die UML wird heutzutage von der OMG, wird sie verwaltet,
weiterentwickelt, es werden ständig, nicht ständig,
aber es werden auch neue Versionen dieser Notation,
also entsprechend also der Veränderung der Aufgaben,
die mit UML-Notationen modelliert werden sollen, gibt es Erweiterungen,
also das wird mittlerweile von der OMG durchgeführt,
das ist so eine Non-Profit-Organisation und die sind diejenigen,
also die ohne eigenes Interesse an der Vermarktung dieser Notation,
diese Notation verwalten.
So, Sie sehen das so, die Unified Modeling Language ist dazu da,
Fragestellung der Anforderungsermittlung bis zu Fragen der Dynamik-objektorientierter Systeme im Ablauf.
Also eine weltweite für alle Arten von objektorientierten Systemen eingängige,
objektorientierte, eine eingängige, ich soll es nur sagen,
Notation bereitzustellen, weil man eben solche Vergegenständlichungen braucht,
um sich die unterschiedlichen Fragestellungen, die sich bei der Entwicklung,
Konstruktion ergeben, um die, also so darstellen zu können,
dass die Leute wissen, worüber man redet.
Sie sehen hier jetzt erstmal nur so als Ausstellung,
ja, so als Auflistung sehen Sie die Diagrammtypen,
die die UML bereitstellt und wir werden uns im Rahmen von SE1 mit genau zweien von denen,
werden wir uns beschäftigen und das beschäftigen ist eigentlich,
das ist keine intellektuelle, große intellektuelle Hürde.
Das sind diejenigen, die wir brauchen, um die Probleme
zu beschreiben, mit denen wir uns hier beschäftigen.
Das ist das sogenannte Klassendiagramm und das Objektdiagramm. Sie sehen hier so die anderen Diagramm-Typen,
die es gibt, nur mal so als Beispiel,
womit wir uns in SE2 auch noch beschäftigen werden, sind sogenannte Pakete.
Das ist die nächstgrößere Ordnungsebene, auf der sie Klassen einsortieren können. Also wenn man feststellt,
also man hat jetzt so und so viel,
ein so und so großes Problem,
kann man dieses große Problem nochmal in kleinere Probleme zergliedern und die Organisationseinheit,
die dafür in der UML zur Verfügung steht,
sind die sogenannten Pakete und das ist auch ein Programmierkonstrukt,
dass sie in Java entsprechend wiederfinden werden.
Das heißt also, für so unterschiedliche Fragestellungen gibt es auch unterschiedliche Arten von Diagrammen,
mit denen sie dieses Problem in einer überschaubaren Art und Weise aufschreiben können.
So, das Objektdiagramm, wie sieht das aus?
Also zunächst mal so als einzelnes Objekt, was beschreibt man da?
So, wir, wir haben uns jetzt gesagt, so,
wir stellen diese Objekte als Rechtecke mit abgerundeten Ecken dar,
das heißt also, das ist keine Klasse.
Jeder weiß, wenn er das hier sieht, aha,
hier ist also ein Objekt, von welcher Klasse ist denn dieses Objekt?
Das ist ein Objekt der Klasse Girokonto. Welche Werte haben die Exemplarvariablen,
die Felder im Moment und mit welchen mit Methodennamen,
mit welchen Operationen kann ich,
also ein Objekt dieser Klasse manipulieren oder genau dieses Objekt
Manipulieren. So sieht ein Objektdiagramm aus,
so ein einzelnes Objekt und dann so Objekte treten ja nie alleine aus,
die Pilze treten immer im Zusammenhang mit anderen Objekten auf.
So, und das Objekt Spielfeld enthält halt Referenzen,
das wissen sie jetzt auch, also was das ist.
So ein Objekt Spielfeld, ein Objekt der Klasse Spielfeld,
enthält in seiner Exemplarvariable Zeile null, wie vom Typ von der Klasse Spielfeldzeile,
ist eine Referenz auf eben eine Spielfeldzeile und die wiederum hat drei Exemplarvariable,
auf die Methodennamen haben wir hier der Übersichtlichkeit,
also mit denen diese Objekte jeweils manipuliert werden können,
haben wir verzichtet.
So, Das sind also Objektdiagramme,
wenn sie also sowas demnächst sehen oder schreiben oder sie aufgefordert werden,
ein Objektdiagramm zu zeichnen, dann malen sie sowas.
Demgegenüber oder ergänzend dazu, die Klassendiagramme, zunächst mal wieder die einzelne Klasse.
Nun, wie beschreibt man eine einzelne Klasse? Wie heißt
sie denn? Die Klasse, Sie sehen hier auch,
also es ist immer schwierig, das negativ zu formulieren.
Sie sehen hier keine abgerundeten Ecken. Sie sehen hier eckige Ecken
und deswegen ist es auch gleich, also eine Klasse erkennbar.
Diese Klasse heißt Girokonto. Sie definiert zwei Exemplarvariablen vom Typ
Betrag und sie hat folgende öffentliche Schnittstelle.
Sie hat folgende Methoden, die diesen Referenztypen ausmachen
Die kann man jetzt, weil die können wahlweise Parameter haben oder keine Parameter haben.
Also jedenfalls ist das eine eindeutige Beschreibung der Schnittstelle dieser Klasse.
Und auch die Klassen kommen nicht, also kommen in der Regel
nicht einzeln daher, sondern die kommen im Verbund her.
Und jetzt kommt die nämlich die entscheidende Frage. Was bedeuten
die Pfeile? Und die UML hat also zwei verschiedene,
mehrere verschiedene Arten von Pfeilen, uns in SE1 beschäftigen im Wesentlichen ausschließlich zwei Arten von Fallen.
Das ist einmal die Benutztbeziehung, die benutzt Beziehung,
die wird so dargestellt, sie ist ein gestrichelter Pfeil.
Die benutzt Beziehung bedeutet, in der Klasse Bankautomat gibt es
irgendwo eine Exemplarvariable oder einen Parameter oder eine lokale Variable vom Typ Girokonto.
Das heißt also, so Klassendiagramme, das ist so,
ich glaube, Blue Jay ist auch in der Lage,
die aus dem Coach zu generieren, die Klassendiagramme zeigen ihnen,
welche Abhängigkeiten sie in ihrem Programm, durch das Aufschreiben von Klassennamen erzeugt haben.
Und dann haben sie halt so, wie das hier steht,
also das, was man hier draus schließen kann aus diesem Diagramm ist,
es gibt in der Klasse Bankautomaten,
gibt es einen Bezug zu der Klasse Girokonto.
Was unter anderem bedeutet, sie können die Klasse,
können niemals ein Objekt der Klasse Bankautomat erzeugen,
ohne dass nicht eine übersetzbare Fassung der Klasse Girokonto zur Verfügung stellt.
Und dasselbe gilt hier für die Beziehung zwischen Bankautomat und Kontoverwaltung.
Und die Enthält-Beziehung ist also vergleichbar mit der Benutztbeziehung Also das ist ein etwas feinerer Unterschied,
weil also die Objekte der Klasse Konto,
die Objekte der Klasse Kontoverwaltung, die Konto,
die Innenkontoverwaltung enthalten sind, sind als Referenzen außerhalb der Kontoverwaltung nicht sichtbar.
Das ist ein etwas feinerer Unterschied,
da kommen wir auch nochmal, also später drauf zu sprechen,
so für den Moment sollten sie einfach nur behalten,
dass also diese Art von Beziehung hier bedeutet,
es sind Objekte von Kontoverwaltung in Bankautomat vorhanden und es sind
Objekte von der Klasse Girokonto
Ihr Klassenname Giroconte. Ich muss das jetzt hier wirklich nochmal genau sagen.
Girokonto ist bekannt im Bankautomaten. So eine Art von Pfeil
habe ich jetzt hier rot gekennzeichnet, nämlich die Ist-Einbeziehung.
Vergessen Sie das. Das ist jetzt nur der Vollständigkeit halber
hier aufgezeichnet. Ist eine Beziehung, die wir uns erst
in SE2 etwas genauer anschauen werden, keine Angst.
Also das kriegen wir auch noch hin.
So, zwei Minuten vor drei wünsche ich Ihnen ein
schönes Wochenende
Und jetzt übergebe ich ans Fred,
um nicht nur das Alias-Problem mit ihnen besprechen zu lassen.
Schönes Wochenende. So, ich bin wieder stimmlich da.
Ist alles in Ordnung mit meiner Stimme. Oh,
der Kameramann ist gar nicht anwesend. Okay. Ich hoffe
dann einfach mal, dass alles in Ordnung ist.
Okay, dann starten wir mal. Ich starte einmal den Internet,
denkst du, ey, Entschuldigung, den Firefox?
Weil ich war gestern irgendwie jedes Mal irgendwelche Ankündigungsankündigungen zu machen.
Einer hatte ja Guido schon gemacht. Aber ich glaube,
ich wollte noch was anderes ankündigen
Was wollte ich denn ankündigen? Das fällt mir bestimmt
gleich wieder ein. Ja, genau, das hier.
Das haben wir also mal rausgekramt aus dem letzten Jahr.
Es gibt also die Möglichkeit für euch festzustellen, habe ich den Stoff,
den wir bis jetzt in der SE1 gemacht haben,
bis inklusive Woche 5, glaube ich, habe ich den einigermaßen verstanden.
Dafür haben wir diesen Selbsttest, den könnt ihr also hier quasi starten.
Ich weiß gar nicht, ob ich das machen kann,
weil ich habe den, glaube ich, schon mal,
ich habe den schon mal gestartet,
ich klicke da einmal rauf und gucke,
ob der das merkt,
dass ich das schon mal gemacht habe
Nee, das scheint ja tatsächlich nicht zu merken,
dass ich das schon mal gemacht habe.
Okay, möglicherweise kann man das mehr als einmal machen.
Genau, und also so sieht so ein Test aus.
Das ist einfach so eine einfache Multiple-Show-Sache. Früher waren auch
unsere Klausuren-Multiple-Shows, das ist mittlerweile nicht mehr so.
Aber trotzdem kann man hier ganz nett schauen,
ob man irgendwie verstanden hat, worum es hier so ging.
Hier so ein bisschen was über Bullischer Ausdrücke, ein bisschen
was über Punkt vor Strichrechnungen. Habe ich den Unterschied zwischen,
noch nicht, hier geht es einfach nur um Parameter,
habe ich den Unterschied verstanden,
zwischen Parameter und Rückgabetyp und Sichtbarkeit und so weiter,
ein bisschen mal was zum Switch-Statement.
Ich glaube, ich weiß gar nicht, ob wir das
schon hatten, dann kommt das nicht erst nächste Woche.
Naja. Habt ihr den Unterschied zwischen formalen und aktuellen Parametern
verstanden und so weiter? Das ist irgendwie ganz nett.
Und das haben wir bis jetzt noch nicht so wahnsinnig
viele Leute gemacht
Wenn ihr also damit einmal fertig seid, dann müsst ihr
hier unten klicken auf Antworten abgeben. Wenn ihr das gemacht habt,
sagt ihr Test abschließen und irgendwie kriegt ihr dann ein Ergebnis.
Würde ich euch empfehlen, nehmt euch mal eine halbe Stunde
Zeit und macht es einfach mal zu Hause.
Genau, und man sieht hier also, naja,
vielleicht so 40, 50 Leute haben das schon gemacht.
Okay. Würde mich also freuen, wenn ihr das tut,
möglichst nicht jetzt, sondern frühestens in der Dreiviertelstunde.
So, dann starten wir mal Blue Jay.
Eine Sache wollte ich noch machen. Ich war völlig irritiert,
als wir letztes Mal so schön Dieses Guess Root implementiert hatten und darauf aufbauen und gesagt haben,
wir brauchen jetzt nur noch drei Iterationen von diesem Newton-Verfahren.
Und irgendwie hatte das für die Zahl 2 nicht so richtig funktioniert.
Wir hatten also Folgendes gemacht. Ich hatte das getestet.
Ich habe gesagt, was ist denn die Wurzel von 81 zum Beispiel?
Und da kam so ein wunderbares Ergebnis raus, neun.
Und dann, ich blöde ja an,
habe dann als nächstes hier raufgeklickt und habe dann gesagt,
zwei, das kann man ja sehr schön bei Electro-Togo sehen.
Und hier wird ja tatsächlich dieses Newton-Verfahren überhaupt nicht angewendet,
sondern nur dieser initiale Wert geraten.
Und das wollte ich jetzt einmal noch mit euch machen,
dass ihr wirklich seht, dass wir da keinen Unsinn programmiert haben,
frettert nur die falsche Operation ausgewählt.
Also wenn ich sage, ich möchte die Wurzel von zwei berechnen,
dann schauen wir doch mal,
wie gut das jetzt ist
Aha, 4, 2, 1, 3, 5,
6, 2, 3. Okay, also ist hier quasi, ne?
Das sind eins, zwei, drei, vier,
fünf, sechs, sieben, acht oder zehn,
elf Stellen hinter einem Komma.
Also jemand meinte, er kann es bis zehn Stellen hinter dem Komma auswendig.
Der wäre also zufrieden gewesen. Gut. Dann... Habe
ich überlegt, was mache ich denn heute mit euch?
Und irgendwie ist es nochmal ganz nett, wenn man irgendwas Grafisches hat.
Ich habe also gestern noch so, ich konnte nicht schlafen.
Ich dachte, was mache ich denn mit meinen Studenten,
dass die irgendwie so ein bisschen Spaß in der Vorlesung haben
Und dann habe ich mal versucht, so ein kleines Spiel zu programmieren.
Ja, also ihr seid dieser Spieler hier,
könnt euch ja so durch die Welt bewegen.
Und ich versuche jetzt mal irgendwie aus der Welt rauszugehen.
Oh, hm, verloren. Das ist ja doof, ne?
Okay. Was? Ach, Beamer, anpassen, Dankeschön.
Zack, zack. Hoffen, dass es sich irgendwie kalibriert.
Solange er sich kalibriert, kann ich aber versuchen zu gewinnen.
Ach so, das ist ja, Kollision ist noch gar nicht eingebaut.
Also normalerweise sollte man hier nicht durchgehen dürfen. Das spart mir jetzt sehr viel Zeit,
das ist gar nicht so schlecht, weil ihr seht,
da ist ja unheimlich langsam dieser Spieler,
aber ich versuche jetzt mal zu gewinnen.
Also das Ziel ist es quasi hier oben rechts,
den Ausgang zu finden
Oh, gleich haben wir es geschafft. Ach, ist das schön,
ja, jetzt muss das Spiel nur noch ein bisschen schwerer machen.
Okay. Und ihr seht hier, in dem Klassendiagramm,
das sind alles Klassen, die wir jetzt quasi zusammen geschrieben
haben oder ich habe sie geschrieben und wir gucken sie uns gleich zusammen an.
Und man sieht hier sehr schön schon die Abhängigkeiten in dem Klassendiagramm.
Also wenn man vielleicht sagen will,
wir versuchen erstmal die Basisbausteine zu verstehen, die einfachste Klasse,
dann fängt man wahrscheinlich am besten hier an.
Wenn wir diese Klasse Line-Secment verstanden haben,
schauen wir uns mal die Klasse Box an,
denn die hängt ja offenbar ab von der Klasse Line-Segment.
Das heißt, irgendwie werden wir erwarten,
dass dieser Typ Line-Segment hier irgendwie drin auftaucht
Und dann werden wir Box und Linezeiten mit verstanden haben,
dann schauen sie als nächstes die Klasse Blogs an.
Das Spiel heißt einfach so, mir ist kein besserer Name eingefallen.
Im Nachhinein ist mir aufgefallen, dass es völlig blöd ist,
weil es ja fast so ähnlich klingt wie Box.
Ich hoffe, ich verspreche mich heute nicht zu oft.
Okay, dann schauen wir uns mal die Klasse Line-Segment an.
Wie gesagt, ich habe sie gestern kurz vor Mitternacht geschrieben.
Im jetzigen Zustand könnte ich die niemals irgendwo veröffentlichen,
weil da überhaupt gar keine Kommentare sind.
Für die Vorlesung ist es nicht so schlimm,
weil meine Aufgabe ist es, euch an euch Quelltext zu erklären.
Also das, was ich jetzt erkläre,
würde normalerweise in den Klassenkommentaren hier normalerweise irgendwie drinstehen.
Wir schauen erstmal Ob wir so von der Komplexität damit klarkommen,
was hier so in der Klasse steht.
Wir haben also ein Zustandsfeld, das ist einfach ein Int,
das kennt ihr schon vom Konto,
oder hatte man zum Beispiel einen Saldo als Int.
Und dann haben wir noch ein Exemplar konstant,
oder das sehe ich an diesem Final.
Größe kennen wir sowas schon, das war auch in dem Konto,
das war da zum Beispiel die Kontonummer.
Das ist also jetzt nicht komplizierter als ein Konto.
Ich habe ein veränderliches Zustandsfeld, ein nicht veränderliches Zustandsfeld,
beide vom Typ Int. Also damit sollten wir eigentlich hoffentlich
keine Probleme haben. Dann haben wir einen Konstruktor,
wo ich einfach nur quasi die Startwerte reinreiche und die werden entsprechend zugewiesen.
Wie war das bei dem Kontobeispiel? Da hatten wir,
glaube ich, einen Startguthaben und das wurde dem Guthaben
zugewiesen,
also extrem ähnlich
Dann habe ich hier die sogenannten Ghetter,
nennt man die ganz gerne, oder die sondierenden Operationen,
die mir einfach nur die aktuellen Werte zurückliefern.
Und voll sequent sich irgendwie dafür interessiert.
Dann habe ich hier sowas, das ist quasi das Einzahlen.
Also ich kann sagen, ich will irgendwie dieses Line-Setman irgendwie
durch die Gegend bewegen, um ein gewisses Delta.
Und dieses gewisse Delta wird dann einfach drauf addiert auf die Position.
Das ist, als würde ich 100 Euro einzahlen wollen,
nur dass es hier nicht Euro sind, sondern irgendeine Positionsangabe.
Okay, und das ist etwas,
was wir noch implementieren müssen, damit diese Kollision später funktioniert.
Also ein Line-Segment hat eine Position, ich beschränke mich jetzt
mal, nee, ich beschränke mich nicht.
Und diese Klasse beschränkt sich tatsächlich auf eine Dimension,
nehmen wir einfach mal zum Beispiel diese Dimension.
Ich sage also irgendwo Hier fängt das Line-Segment an und
dann habe ich eine gewisse Breite. Vielleicht 20 ist,
glaube ich, die Breite von meinem Spieler.
Also irgendwo ist quasi die linke Kante des Spielers und wie breit
ist er zum Beispiel 20? Und durch diese Move-Operation hier
unten kann ich jetzt quasi dieses Line-Segment so durch die Welt bewegen.
Wenn ich also irgendwie Curse links oder Kassa rechts drücke,
dann bewegt sich da irgendwie was. Warum das passiert,
werden wir gleich noch sehen. Also ein Line-Segment,
wenn du es einfach nur eine eindimensionale, beschränkte Linie,
die man durch die Gegend schieben kann,
aber die Breite ist immer dieselbe oder die Größe.
Gut, das hier müssen wir noch machen.
Vielleicht hätte ich da mal To-Do reinschreiben sollen
Okay. Gibt es zu dieser Klasse bis jetzt
erst mal Fragen, was hier bestimmte Dinge bedeuten?
Oder ist das erst mal irgendwie klar? Ein Lines-Segment hat
eine Position und eine Bereitung und die Position kann man ändern.
Ja. Es ist egal, was ein Hobbit zur Folge zu dem Klassiker ist.
Es ist hier sozusagen noch gar nicht definiert.
Das funktioniert für alle Dimensionen. Und wir werden gleich das
für mehrere Dimensionen uns zusammenbasteln. Das ist dann der interessante Schritt quasi,
was dann auch das Thema der heutigen Vorlesung ist.
Okay, dann schauen wir jetzt also mal. Wir würden jetzt also erwarten,
dass dieser Typ Lines-Segment in der Klasse Box irgendwo auftaucht,
weil sonst hätte BlueJay diesen Fire nicht generiert.
Guido, hat er ja schon gesagt,
dass Bluejay diese Klassendiagramme euch quasi direkt aus dem Quelltext erzeugt.
Und das ist auch so. Also ich habe diese Pfeile hier nicht hingemalt.
Das ist der Bluejay von alleine gemacht. Okay,
dann schauen wir doch mal, wie so eine Box aufgebaut ist.
Ob wir das verstehen. Gut. Das ist jetzt spannend. Das ist,
glaube ich, das erste Mal, dass wir eine Klasse schreiben,
wo die Zustandsfelder nicht einfach nur Ind oder Bulien oder Float sind,
sondern Typen, die wir selber geschrieben haben.
Wir haben uns ja gerade dieses Line-Segment angeguckt.
Und jetzt taucht das hier wieder auf als Typ von Zustandsfeldern.
Das bedeutet also, ein Exemplar der Klasse Box hat
zwei Referenzen auf Line-Segment-Objekte
Das gucken wir uns gleich vielleicht auch nochmal interaktiv in Blu-Jay an.
Okay, also eine Box besteht aus zwei Line-Segments. Einmal ein horizontales Line-Segment,
wo ich also sage, nach dem Motto,
wo ist der Spieler gerade in der Welt und wie breit ist er?
Und dieses ist es, ja, wo er quasi auf
der Y-Son-Achse quasi in der Welt ist und wie Hochhässer.
Sehr schön. Das ist also der Zustand einer Box.
Okay, dann gucken wir uns den Konstruktor an.
Hier werden einfach nur vier Ins übergeben, das kennt ihr schon.
Und das ist jetzt spannend. Hier erzeugen wir uns jetzt Line-Segment-Objekte,
also das horizontale Line-Segment startet halt bei X und hat eine gewisse Breite.
Das sind also diese beiden ersten formalen Parameter des Konstruktors
Und das vertikale Line-Segment startet eben bei dem Y und hat eine gewisse Höhe.
Das sind diese beiden formalen Parameter. Die werden da einfach nur so durchgereicht.
Okay, wenn ich das jetzt nicht machen würde,
dann würde in diesen Referenzvariablen die sogenannte Null-Referenz drinstehen.
Ich weiß gar nicht, ob Pido darüber gesprochen hatte. Das heißt,
ihr habt zwar eine Variablung, die auf ein Line-Segment zeigen kann,
aber solange ich nicht sage, hey,
hier ist ein Objekt, zeig mal auf dieses Objekt,
wird sie oft kein Objekt zeigen.
Ihr müsst euch also immer davon quasi vergewissern, hey,
wenn ich so ein Zustandsfeld habe von einem Referenztyp,
wo erzeuge ich denn das entsprechende Objekt oder kriege ich das vielleicht reingereicht,
das Objekt, dann will ich darauf weisen.
Also ich erinnere mich noch,
am Ende der Vorlesung 3 hatten mich mehrere Leute gefragt,
wieso muss man denn immer schreiben, Quadratwand gleich New Quadrat?
Das ist exakt derselbe Fall. Wenn ihr einfach nur Shop
Quadrat wandt und ihr versucht anschließend irgendwas mit dieser Wand zu machen,
wird das Laufzeitsystem sagen, es gibt gar keine Wand.
Ich habe eine Variable, wo eine Nellreferenz drin ist und
du hast noch gar kein Wandobjekt erzeugt.
Also das ist die Referenzvariable und hier wird das Objekt erzeugt und
durch diese Zuweisung binde ich jetzt quasi die Referenzvariable an das Objekt.
Hatte Guido sehr schöne Folien dazu, das zu visualisieren
Okay, dann habe ich immer wieder so ein paar Ghetter.
Also wenn ich das X haben will,
frage ich mein horizontales Objekt nach seiner Position,
wenn ich die Breite haben will,
frage ich mein horizontales Objekt nach seiner Größe.
Also man kann also ja auch ganz wunderbar normal jetzt hier mit diesen Objekten reden,
so wie ihr das vielleicht schon kennt,
wenn man das in irgendwelchen Methoden Variablen hatte.
Das geht eben auch mit Zustandsfeldern von Referenztypen.
Ich kann also einfach diese Anfrage weiterleiten.
Ich rufe einfach die entsprechenden Operationen auf den beiden Projekten.
Okay, dann gibt es ja auch zwei Move-Operationen.
Also wenn ich zum Beispiel horizontal mich bewegen will,
dann muss ich dem horizontalobjekt sagen, dass es sich bewegen soll,
wenn ich mich vertikal bewegen will, muss ich dem Vertikal-Objekt sagen,
dass es sich bewegen soll.
Und das hier müssen wir später
noch implementieren
Hier sieht man also schon ziemlich viele interessante Eigenschaften von Referenztypen,
die für euch sowohl jetzt in der Übung als auch im,
solange ihr mit Java programmieren werdet, relevant sein werdet.
Also ich deklariere mir an der Referenzmariaple,
ich erzeuge ein Objekt und binde es dann an diese Referenzvariable.
Dann kann ich Operationen an dem Objekt aufrufen,
sozusagen indirekt über diese Referenzvariable. Ja,
das passiert hier und da und hier passiert das auch und
hier auch und hier auch ganz normal mit der Punktennotation,
die ihr schon kennt.
Okay, vielleicht erzeugen wir uns mal so eine Box
und schauen uns mal zur Laufzeit an,
wie das aussieht.
Also ich erzeuge mir
eine Box
Und ja, bin in eine Uhr. Ja, ich nenne sie
Box eins, ist egal. Keine Ahnung, 50,
20, Pomdat, 25, völlig beliebig gewählte Zaun.
So. Und jetzt werde ich mir mal anschauen,
wie sieht dieses Objekt eigentlich aus? Wollen wir nochmal raufklicken?
Ich klicke jetzt hier doppelt drauf und jetzt sehen wir das Objekt.
Und bis jetzt war es bei euren Objekten so,
da waren irgendwie hier Inns oder so oder Buliens oder Floats
und dann war die Geschichte gegessen.
Man hatte ein Objekt und das war irgendwie halbwegs
interessant und dann war die Geschichte vorbei.
Hier ist die Geschichte jetzt aber deutlich spannender.
Wir sehen also ein Exemplar der Klasse Box
Hatte zwei Zustandsfelder, horizontal und vertikal.
Und da sind jetzt keine Line-Segments drin, sondern nur Referenzen.
Also Referenzen werden im Dude so dargestellt.
Einen Punkt, dann geht das um Fallen los.
Also hier stehen jetzt nicht irgendwelche Zahlen drin,
5 oder 20 oder 100 oder so, sondern nur ein Verweis,
wo das entsprechende Line-Segment quasi im Hauptspeicher steht.
Da muss ich also auch nochmal extra draufklicken. Und dann seht ihr
das entsprechende Objekt. Und hier kann ich das genauso machen.
Ich klicke auf und dann sehe ich das entsprechende Objekt.
Und ich mache jetzt vielleicht ein paar Folgendes.
Ich mache mal einen Screenshot. Wie mache ich das denn
so? Ah, okay. Ja, ganzer Bildschirm.
So, dann öffne ich das mal mit meinem Lieblingsprogramm
Und was wir jetzt mal machen können, ist,
wir versuchen jetzt mal so eine Art OML-Objektdiagramm.
Also es ist, es ist ein bisschen Freestyle,
sag ich mal. Es ist nicht wirklich OML,
aber ich versuche das mal so ein bisschen.
Ich mache vielleicht mal die Pfeilfarbe anders. So,
also quasi von hier aus, oh Gott, das ist fett.
Nee, das gefällt mir nicht. Da ärgere ich mich
später wieder. Also machen wir mal nur zehn.
Von hier aus geht quasi ein Pfeil zu diesem Objekt.
Und von hier aus geht ein Pfeil zu diesem Objekt.
So. Und dann nehme ich mal dieses schöne Rot, was hier ist.
Und Jetzt kann das reichen. Habe ich jetzt was?
Warum ist der Fall immer so mega dünn? Vielleicht mache
ich ihn doch mal wieder ein bisschen dicker für meine nächste Aufgabe.
Ich muss jetzt hier so ein bisschen zensieren,
denn Objekte haben ja gar keine Namen.
Also weg damit. Das ist so eine komische Blue-Jay-Eigenschaft.
Wenn ich also auf eine Referenzvariable draufklicke, dann denkt Blue-Jay,
es wäre sinnvoll, den Namen der Referenzvariabler als Namen des Objekts hier einzutragen.
Und dann verschwimmt wieder so ein bisschen diese Unterscheidung zwischen Variablen und Objekt.
Das finde ich völlig verwirrend für Anfänger.
Also nehmen wir das mal wieder weg. So. Okay,
und in OML-Diagrammen sind natürlich auch nicht irgendwelche Buttons,
die nehme ich vielleicht auch mal weg
Okay, also die sind immer so als Andeutung,
die anderen würde ich jetzt natürlich auch wegnehmen und so weiter.
Und dann, wenn ich das alles gemacht habe,
dann habe ich schon etwas, was eigentlich sehr,
wie ein UML-Objekt ja gerade mal aussieht.
Und in der Übung verlangen wir von euch, dass ihr das macht.
Also macht das bitte nicht so wie ich jetzt.
Ich wollte es nur nicht komplett frei anzeichnen. Nehmt euch wirklich ein Stück Papier,
malt diese runden Boxen, sagt oben immer, hey,
von welchem, von welcher Klasse,
wie ist denn dieses Exemplar oder von welchem Typ?
Dann macht ihr hier die Variablen hin und wenn es nicht um Referenzvariablen handelt,
dann zeichnet ihr solche Pfeile zu den weiteren Objekten,
mit denen ihr da zu tun habt.
Und das ist so die Komplexitätsstufe von der ersten Aufgabe,
wo ihr das machen müsst.
Ein Objekt hat zwei Referenzen und zwei andere Objekte.
Diese Objekte haben keine Referenzen mehr.
Und in der nächsten Aufgabe sind das dann ein paar mehr
Ja. So versuche ich mir immer solche Objekte ja damit zu zeichnen,
wenn ich kein Stift und Papier zur Hand habe,
aber ihr habt das dann ja hoffentlich.
Ja, dazu noch irgendwelche Fragen. Ich glaube nicht,
ne? Nö, das ist eigentlich recht einfach. Okay
, haben wir das also verstanden? Jetzt wollte Guido ja
unbedingt, dass ich was über das alias Problem erzähle.
Ich gucke mal kurz, ob ich das irgendwie hinkriege hier.
Ich kann mir mal so ein neues Line-Segment machen.
Ich muss da ja zwei Zahlen dranstecken,
ist mir auch erstmal egal, welche.
So, das Ergebnis dieses New-Aufrufs ist so eine Objektreferenz,
die ziehe ich mir jetzt mal hier rüber,
nenne ich mal
Und ich ziehe sie mir nochmal rüber. Und nenne sie
B. Also ich habe euch bis jetzt mal beschummelt.
Ich habe ja behauptet, hier würden irgendwelche Objekte liegen.
In Wirklichkeit liegen hier nur Referenzen. Okay,
wir können ja mal fragen, hey, A. Position zum Beispiel,
an welcher Position liegt denn das Line-Segment, auf das die Variable A verweist?
Das ist an der Position 10. Okay,
dann wollen wir das vielleicht mal ein bisschen durch die Gegend schieben,
vielleicht um 100. Oh, achso, das ist ein Statement,
da müssen sie mir Colan dahinter.
Und dann gucke ich mal,
wo es jetzt ist
An der Stelle 110, so wie wir uns erwartet.
Und was ist, wenn ich jetzt B-Punkt-Positionen sage?
Habt ihr so eine Intuition schon dafür oder seht ihr das
schon im Kopf, das Problem oder was da denn zurückkommen wird?
In einer Nutzwahl. Du hast, glaube ich,
heute Abend das gesagt. Das heißt, du hast
so 10, 500 Euro.
Deswegen kommt welcher Wert raus
Genau, wir beobachten dieselbe Position, also 110. Sehr schön. Also das,
was ihr jetzt im Kopf haben solltet, ist irgendwie,
es gibt die eine Referenz, ah,
es gibt die andere Referenz B,
irgendwie schwebt über denen so dieses Objekt und beide verweisen auf dasselbe Objekt.
Und egal über welche Variable ich das Objekt verändere,
ich kann es dann über beide Variablen auch tatsächlich beobachten,
dass es sich verändert hat.
Das hat zum Beispiel folgenden Effekt. Ich habe hier in dieser Klasse
Box nirgendwo ein Getter oder eine sondierende Operation geschrieben, die dieses Line-Segment zurückliefert.
Das habe ich deswegen nicht gemacht. Wenn ich das machen würde,
dann hätte ich jetzt ja mein Klient eine Referenz auf dasselbe Objekt
wie ich und könnte das irgendwie so durch die Gegend schieben oder irgendwas damit machen,
was ich vielleicht nicht will oder was vielleicht irgendwie sinnlos wäre oder so.
Vielleicht will ich das jedes Mal longen oder auf die Konsole
schreiben oder verbieten, dass das in irgendwelche negativen Richtungen schiebt.
Das könnte ich dann nicht mehr kontrollieren. Also meistens ist es so,
dass man, wenn man Zustandsfeld hat von Referenztypen,
dass man die Objekte, auf die man zeigt,
sehr selten nach außen rausreicht, weil das eigentlich fast immer Probleme gibt.
Okay. Gut, jetzt sind wir aber noch nicht so
weit, dass wir das Spiel verstanden haben.
Wir haben das Line-Segment verstanden, in einer Dimension Position und Breite.
Dann haben wir die Box verstanden, in zwei Dimensionen,
Position und Breite. Und jetzt müssen wir uns auch um
das Spiel an sich kümmern. Schauen wir doch mal,
wie das aufgebaut ist
Wieder mit unserer Brille Referenztypen als Zustandsfelder. Okay,
vielleicht erstmal das, was nicht so angsteinflößend ist,
wir haben hier vier Buliens und jeder dieser Buliens merkt sich,
ob ich gerade auf eine entsprechende Cursor-Taste drücke.
Also wenn ich gerade Cursor links gedrückt halte,
dann ist diese Variable Schuhe, ansonsten ist sie False.
Wenn ich gerade Cursor rechts gedrückt halte, dann ist
die Schuhe, ansonsten ist sie False und so weiter.
Das passiert natürlich nicht auf magische Art und Weise,
nur weil die so heißen,
den Code seht ihr dann irgendwo hier unten,
könnt ihr euch in Ruhe mal angucken, wenn euch das interessiert.
Aber worum es ja eigentlich in der Vorlesung geht,
sind ja Referenztypen und das seht ihr hier.
Wir haben also viermal, wenden wir hier boxen.
Ich sage also, das Spiel Blogs besteht aus vier Boxen.
Eine Box für den Spieler. Eine Box für das
erste Hindernis, das zweite Hindernis und das dritte Hindernis.
Das sind einfach insgesamt vier Boxen. Ja,
und ich erzeuge sie hier vielleicht richtig,
das mal ein bisschen anders aus, dass ihr das sehen könnt,
dass das wirklich immer gleich aufgebaut ist.
Ich sage also, der Spieler fängt ganz links an,
hat eine breite 20, dann so ungefähr in der Mitte
des Bildschirms und hat auch die Höhe 20.
Der Bildschirm ist, glaube ich, 500 mal 500 in meinem Beispiel.
Und dann habe ich hier mit den Zahlen entsprechend so rumgespielt,
dass es dann eben hinkommt,
dass die Obsttückel so halbwegs sinnvoll verteilt sind
Bromster vielleicht auch mal, ein Diagramm von machen. Zumindest anfangen,
das mit den Pfeilen malen, muss ich ja nicht machen.
Aber wenn ich also dieses Spiel mir gemacht habe,
können wir einfach mal reinschauen, wie sieht denn das Spiel jetzt aus?
Was ist der Zustand des Spiels?
Schon ein bisschen komplizierter. Ich habe auf dem Aufgabenblatt,
habt ihr eine andere Aufgabe, die aber so ähnlich ist?
Da sage ich dann extra, hey,
kümmert euch mal nur um die ersten vier Referenzvariabt in den Rest,
könnt ihr mal ignorieren, dass wir unseren Fall nicht so interessant.
Also wir sehen hier tatsächlich ein Exemplar der Klasse Blocks, enthält vier Referenzvariablen.
Hier seht ihr die Referenzen schön darauf ist dargestellt.
Das tue ich also jetzt mal hier irgendwie so ganz nach links.
Und wenn ich jetzt diese Referenzen verfolge, Das ist also die erste Box.
Das ist die zweite Box. Das ist die dritte Box.
Das ist die vierte Box. Und jetzt denkt ihr euch bitte
die Pfeile. Also von hier geht ein Pfeil noch da,
von hier jeden Pfeil noch da und so weiter.
Und hier sind jetzt auch wieder Referenzen drin.
Hier kann ich das jetzt auch wieder raufklicken. Ach,
das ist also dieses horizontale Line-Segment von der Playerbox.
Das ist das vertikale Line-Segment von der Playerbox.
Und hier könnte ich das jetzt auch machen.
Und dann hätte ich 1, 2, 3,
4 plus die 18, hätte ich schon 13 Objekte,
die irgendwie so miteinander verbunden sind über Referenzen.
Klingt erstmal ziemlich komplizierter, wenn man sich jeweils auf einen,
also wenn man das einmal verstanden hat,
versteht man das hier ja genauso.
Also man würde versuchen, erstmal zu verstehen,
diesen Zusammenhang zu verstehen. Und wenn man den verstanden hat,
würde man versuchen, diesen Zusammenhang zu verstehen.
Und genauso haben wir es ja auch vorhin gemacht.
Wir sind ja von unten so langsam nach oben hochgegangen in diesen Abstraktionsebenen quasi.
Okay, und dann eben diese Variablen noch.
Ja. Habt ihr quasi zu dieser Objektstruktur erstmal noch Fragen?
Also das Spiel besteht aus vier Boxen und jede Box
besteht aus zwei Line-Segments für die beiden Dimensionen, ja?
Kann ein Objekt sich selbst referenzieren? Ja, das geht.
Ein Objekt kann sich direkt selbst referenzieren oder auch über Umwege.
Also zum Beispiel, ich könnte eine Referenz,
ich könnte irgendwie 500 Referenzen haben auf alle meine Studenten
Alle meine Studenten haben eine Referenz auf ihren SE1-Dozenten und dann
könnten wir uns gegenseitig referenzieren. Das geht auch, ja.
Kann man machen. Da kommen auch noch sinnvolle Beispiele zu.
Ich glaube, so eine Woche zehn oder elf.
Ja, sonst noch Fragen? Ja. Was ist der
Unterschied zwischen einer Referenz und einer? Users, also benutzt
Beziehungen. Die Referenz ist quasi das technische Mittel,
was man in Java oder C-Plus-Plus oder so hat.
Und die Benutzbeziehung ist das, was du dann im Diagramm
siehst mit diesen gestrichelten Pfeilen veranschaulicht sozusagen.
Also das eine ist auf der Diagrammebene und das andere ist
auf der Java-Ebene
Ja. Vielleicht, wenn man das ganze Programm auch in
einer Klasse stellt. Hätte man das ganze Programm in einer
Klasse schreiben können, ja, hätte man machen können.
Das wäre, das hätte dazu geführt, dass das Klassendiagramm
relativ langweilig gewesen wäre. Und dass sehr viele Variablen,
oder ich sag mal so, die Anzahl der Variablen wäre explodiert.
Weil ich hätte ja sozusagen in dieser Klasse, hätte ich,
glaube ich, schon 16 Variablen gebraucht für die eine Box, oder?
Nee, warte mal. Nee, vier für die eine Box.
Also ich hätte, glaube ich, schon 16 Variablen für die Boxen gebraucht.
Kann jemand anderes aussehen. Vielleicht sind es auch mehr als 16.
Und vor allem die ganze Logik, Dinge zu verschieben,
hätte ich dann auch für jede Box neu programmieren müssen.
Mir ist das irgendwann mal aufgefallen, als ich früher so meine ersten Spiele programmiert habe.
Und ich wollte sie aus einer Einspieler-Variante auf eine Zweispieler-Variante ausdehnen.
Ist mir aufgefallen, huch, ich muss jetzt alle meine
Variablen verdoppeln. Also vorher hatte ich eine Variable X,
jetzt brauche ich eine Variable X für Spieler 1 und X
für Spieler 2. Und bis ich dann irgendwann gemerkt habe,
hey, es ist ja viel einfacher,
eine klasse Spieler zu haben und dann einfach zwei Objekte davon zu erzeugen.
Also das Ziel ist es eigentlich immer,
so wenig Redundanzen wie möglich zu haben.
Gut. Okay, also da haben wir jetzt,
glaube ich, die Struktur so einigermaßen verstanden,
wieder so die Referenzen auf die Objekte zeigen
Dann versuchen wir doch mal als nächstes zu verstehen,
wie hier überhaupt was angezeigt wird. Bis jetzt haben wir
das, ist das alles irgendwie so intern am Rechner.
Wie kommt das denn jetzt dazu, dass man überhaupt irgendwas sieht?
Das liegt an dieser Methode Draw. In dieser Methode Draw
könnt ihr irgendwie rumhühnern und andere Dinge zeichnen. Ich stelle mir mir vor,
dass irgendwie fünf bis zehn Prozent der Studenten sich bestimmt das
gleich runterladen und da rumspielen wollen mit dem Spiel, also weiterentwickeln.
Hier wird also festgelegt, was der Spieler tatsächlich sieht. Ich sage als erstes,
ich habe hier so eine Variable quasi für die Leinwand,
sage ich jetzt mal ganz leihenhaft ausgerückt,
was das genau ist, lernt ihr, glaube ich,
gar nicht in SE1 und SE2. Könnt ihr euch aber selber anlesen.
Ich sage also alles, was als nächstes gezeichnet wäre,
soll grau sein.
Und dann möchte ich
meine drei Obsticals zeichnen
Anschließend soll alles, was als nächstes gezeichnet werden soll, schwarz sein.
Und dann mache ich den Spieler. Also das erste,
was wir jetzt mal machen können, ist zu sagen,
nö, schwarz ist mir irgendwie zu depressiv.
Ich mache den Spieler mal blau. Mal gucken,
ob das, ob das irgendeine Auswirkung hat.
Tja, jetzt ist er blau. Wahnsinn, oder?
Rede ich mal gleich ins Verderben.
Die Farbe gefällt mir nämlich nicht so gut.
Okay. Und dieses Draw ist einfach diese Hilfsmethode hier unten.
Ich weiß nicht, ob ihr sie alle sehen könnt.
Also, und hier sieht man jetzt auch wieder wunderbar,
dass man Referenztypen zum Beispiel als Parameter übergeben kann.
Also ich rufe diese Draw-Funktion oder die Draw-Methode hier unten auf.
Und hier ist jetzt ja ein formaler Parameter vom Typ Box.
Das heißt, hier wird erwartet,
dass ich eine Referenz auf eine Box übergebe,
zum Beispiel diese
Oder diese später oder noch später, diese und ganz am Ende
diese. Diese Drow-Methode kann also jede beliebige Box zeichnen.
Ich muss ihnen nur sagen, welches sein soll.
Okay. Dann sagt der Leinwand, hey,
füll doch mal ein Rechteck aus. Heißt Red Tankle Rechteck?
Ich glaube ja, ne? Füll doch mal ein Rechteck
aus. Das ist die X-Koordinate, das ist die Y-Koordinate,
das ist die Breite und das ist die Höhe.
Das erwartet einfach diese vier Parameter an der Einfangung.
Und das ist jetzt irgendwas in Java eingebautes.
Diese Methode habe ich also nicht geschrieben. Das ist einfach
schon in Java drin. Könnt ihr euch die Dokumentation dazu
durchlesen, wenn ihr wollt. Aber ich glaube,
man versteht das auch so ganz gut,
wenn ich eine Rechteck zeichnen will, muss Java ja irgendwie wissen,
wo soll das denn liegen und wie groß soll es denn sein?
Und hier telegiere ich auch schon wieder Anfragen an meine Zustandsfelder
hier sozusagen, wunderbar, mit der Punktnotation.
Gibt es zum Zeichnen erstmal Fragen? Nö. Ja. Das Ziel ist,
man tut mir alles tut, für Fragen im Padio abletzt,
die Söhne, der selbe Dame, das ist der Ziel,
der Söhne.
Ah, ah, okay, das. Das ist interessant.
Ich glaube, das kam tatsächlich noch nicht in der Vorlesung
dran. Du hast dich gewundert, dass eine Methode Jaw
hier oben ist ohne Parameter und eine Methode Jaw hier
unten mit einem Parameter
Stimmt, das habe ich jetzt irgendwie untergeschummelt, dass das geht.
Das haben wir noch gar nicht besprochen. Man sagt die Methode,
der Methodenname ist überladen. Also ihr könnt tatsächlich mehrere Methoden haben,
die gleich heißen, sich aber in ihrer Parameterliste unterscheiden.
Also an dieser Stelle stellt Java fest, ah,
der Programmierer will eine Draw-Methode aufrufen mit einem Parameter
und dann kann es ja eigentlich nur diesig hier sein.
Nur wenn an einer anderen Stelle im Quelltext rufe ich eine
Draw-Funktion ohne Parameter auf, dann ist ihm irgendwie klar,
das kann nur diese sein.
Also das kann man machen. Ja, Entschuldigung. War
mir nicht klar, dass ich ihn noch gar nicht erklärt hatte.
Okay. Jo, dann soll man den Spieler ja
auch durch die Gegend bewegen können,
habe ich eine eigene Methode für geschrieben
Schauen wir mal, ob wir hier nicht auch mal was ändern können,
weil das Spiel war ja so langsam gerade.
Das hatte wirklich gar keinen Spaß gemacht. Okay,
Ist kennen wir ja, ne? Also ich frage,
welcher Wert steht jetzt gerade in dieser bulischen Variable Cursor Left Press drin?
Das hatten wir letzte Woche mit den Ampeln, ne?
Man kann also tatsächlich in ein If einfach so eine bulgische Variable reinschreiben.
Wenn da der Wert Crue drinsteht, dann wird das hier ausgeführt.
Ansonsten wird das unter dem Els gemacht. Okay,
also wenn das gemacht wurde, dann wird da quasi um
einen nach links geschoben. Okay. Warum nicht als Weil
? Das ist eine sehr gute Frage.
Warum nicht als Wireschleife
Wir reden ja hier über sequenzielle Programmierung. Wenn du ja eine Wild-Schleife hast,
und ich sage, solange der Spiele nach links drückt,
ziehe einen von seiner Position ab, dann wurdest du aus dieser Wild-Staffel
nie rauskommen und es würde zum Beispiel nichts gezeichnet werden.
Es würde nicht reagiert werden, ob der Spieler gegen eine Wand gelaufen ist oder nicht.
Du würdest die ganze Zeit in dieser Wild-Schleife,
dann steckt der Rest, der Spieleguck würde gar nicht weitergehen.
Also das System sorgt im Hintergrund irgendwie dafür,
dass ständig in Abwechslung diese Methode und diese Methode aufgerufen wird,
immer so im Wechselzyklus.
Schauen wir uns euch an, das ist total trivial.
Und da ist es dann, glaube ich, tatsächlich eine Wild-Schleife, oder?
Ich gucke gleich mal. Okay, was könnte ich denn
jetzt tun, damit das Spiel schneller geht?
Genau, eine höhere Zahl als eins.
Wollen wir mal vielleicht zwei nehmen? So, schauen,
ob das jetzt schon deutlich mehr Spaß macht.
Jo, das ist doch schon nicht schlecht.
Okay, vielleicht würde ich noch ein bisschen schneller haben.
Jetzt zeige ich euch mal einen kleinen Trick.
Jedes Mal, wenn ich eine andere Geschwindigkeit haben will,
muss ich jetzt an vier Stellen im Quelltext mit Zahl ändern.
Das ist ja irgendwie blöd, ne?
Vielleicht machen wir mal Folgendes. Ich mache mir einfach mal
eine kleine Variableche oben. Ich nenne die mal Flight Speed.
Setze die Flamme auf fünf
Und dann sage ich hier jeweils minus Speed und plus spielt
das Plus ist hier optional, aber ich finde das irgendwie schön,
wenn da drüber ein Minus steht,
dann ist das irgendwie symmetrischer mit dem Plus.
Static haben wir, glaube ich, noch gar nicht kennengelernt, oder?
Ich glaube, Static kommt, das ist eine Woche zehn oder elf,
deswegen will ich da jetzt noch nicht drüber reden.
Ja, aber du hast recht. Also wenn du es programmierst
, machen es Static-Graphe. Okay, schauen wir mal,
ob das jetzt noch mehr Spaß macht.
Dann würde ich nämlich gleich nochmal gewinnen wollen.
Das fühlt sich mal so gut an. Ah, zack
. Aber ich kann jetzt mal, jetzt bin ich mal
ganz ehrlich und mach mal hier so, oh, runterladen.
Das war knapp, ne? Das war wirklich knapp.
Okay. War jetzt guter Endsport. Und zack. Okay
. Gut. Ihr wart irgendwie ein Begeisterter beim ersten Mal
, oder? Okay. Okay,
und dann haben wir hier noch so ein paar Methoden,
die abprüfen, hat der Spieler gewonnen,
ist er irgendwie aus der Welt rausgelaufen oder ist er irgendwie in eine Wand reingelaufen?
Also ich habe hier einfach mal definiert, wenn die X-Position
des Spielers mindestens 500 ist, dann hat er gewonnen.
Dann bin ich nämlich genau aus dem Bildschirm rausgelaufen rechts sozusagen
Dann habe ich gesagt, wenn er links aus dem,
also wenn er den linken Bildschirmrand quasi schon berührt,
ist schon mal schlecht, dann, das war keine gute Idee.
Wenn er den Bildschirmrand oben berührt, also Y-0-
0 ist oben, in der Mathematik wäre es unten,
das ist jetzt auf dem Computer genau andersrum.
Dann hat er verloren. Oder wenn er unten schon anfängt,
irgendwie den unteren Bildschirmrand zu berühren,
dann ist es auch irgendwie nicht so gut.
Haben wir mal wieder eine kleine Wiederholung, Bulle Schale,
das ist doch irgendwie auch ganz nett.
Ja, und das ist jetzt eben noch nicht implementiert.
Hm. Und jetzt haben wir zwei Möglichkeiten.
Also wir haben in diesen drei Klassen jeweils eine Methode,
die wir noch implementieren müssen. Und wir können jetzt sagen,
wir fangen High-Level an, das ist meistens für die Programmieranfänger
so ein bisschen blöd.
Ach,
dann müssen wir
Methoden benutzen
Die noch gar nicht implementiert sind. Wir machen das jetzt mal andersrum. Also,
wir sind jetzt in der Klasse Line-Segment und ich habe hier
eine Methode vorbereitet, der übergebe ich quasi ein zweites Line-Segment.
Also, wenn ich diese Methode von außen aufrufe,
zum Beispiel, wenn ich sage a.colights with B,
dann möchte ich wissen, ob die Line-Segments A und B kollidieren miteinander.
Also, die würden nicht kollidieren,
die würden zum Beispiel kollidieren und so auch und so auch.
Und so würden sie wieder nicht kollidieren. Ja,
das muss ich irgendwie berechnen. Das ist eine tolle,
spannende Hausaufgabe eigentlich, aber ich kann euch jetzt ja nicht
nach Hause schicken. Dass man sich also irgendwie überlegt,
okay, ich habe also diese beiden Varianten,
Position und Größe
Einmal für einen Line-Segment, einmal für ein anderes Line-Segment.
Wie kann ich jetzt mathematisch bestimmen, ob die kollidieren oder nicht?
Vielleicht könnt ihr da mal eine Minute drüber nachdenken.
Ich starte das System noch mal kurz, wenn man das
grafisch sieht, ist das vielleicht ein bisschen inspirierend.
Also, ich habe also dieses Line-Seg,
also wir nehmen jetzt mal nur das Horizontale.
Ich habe also dieses horizontale Line-Segment und hier gibt es
ein horizontales Line-Segment und noch ist ja alles in Ordnung.
Die Welt, boah, ich bin aus der Welt rausgelaufen,
das wollte ich nicht. Noch ist alles in Ordnung
und jetzt auch und das ist auch noch in Ordnung.
Ja, das ist gerade grenzwertig sozusagen. Und wenn ich jetzt
noch einmal nach rechts drücke, dann ist es irgendwie ein Problem.
Was ist denn da mathematisch passiert? Was ist denn an die,
ich mache noch vielleicht so, was ist denn an dieser Situation anders als an dieser?
Rein mathematisch. Vielleicht mal so ein paar Ideen.
Wir sind ja nicht an einem äußeren Rand von der Bobby Safe,
ist aber außerhalb des Körpers Spielen. Tennis wird gezeigt,
der zumindest die logischste Geschichte, die ich gesehen habe.
Er sagt doch, sind wir halt auf der Lippe.
Das hat mich eine sehr generische Antwort.
Ich starte vielleicht noch einmal ganz kurz ein Bild Editor
Und wir versuchen, es einfach mal systematisch klarzumachen, welche Fälle es eigentlich so gibt.
Ich glaube, sonst kommen wir nicht wirklich voran.
Wie gesagt, also wenn man das mal alleine macht,
also wer jetzt nur online schaut,
pausiert das Video und versucht mal zehn Minuten drüber nachzudenken.
Also ich versuche jetzt einfach mal hier ein Line-Segment zu malen
und jetzt alle Möglichkeiten, mit denen ein anderes Line-Segment,
mit dem in Beziehung stehen könnte, mache ich das mal blau.
Also wir können ja zum Beispiel sagen,
es könnte zum Beispiel hier sein, ja,
dann haben wir sozusagen kein Problem.
Es könnte sein, dass es da schon so halb reingewandert ist.
Es könnte sein, dass es komplett da drin ist.
Es könnte sein, dass es das andere komplett umfasst.
Es könnte sein, dass es hier rausgewandert ist und es
könnte sein, dass es das gar nicht berührt.
Vielleicht hätte ich
das mal grün machen sollen
Machen wir, ich überzeichne das jetzt einfach mal grün,
vielleicht mal ein bisschen dicker, dass ich alle Pixel erwische.
Also das ist sozusagen der Fall, keine Kollision,
das ist der Fall, keine Kollision.
Und in anderen Fällen gibt es Kollisionen, egal ob wir
jetzt partiell sind oder irgendwie das eine komplett in dem anderen oder andersrum.
Und das Spannende ist, das ist mir irgendwann mal aufgefallen,
ich glaube, als ich einen Tetris programmiert habe oder so,
dass man diese ganzen Fälle hier drin,
wenn man die jetzt alle ausprogrammiert, vier Stück, wird man bekloppt.
Was viel einfacheres ist zu sagen,
ich mache mir immer so einen Gedankenstrich rein,
Wir kümmern uns nur um die Fälle, die nicht kollidieren,
denn davon gibt es nur zwei.
Und dann negieren wir das einfach. Also wenn ich
irgendwie berechnen kann, dass zwei Linien nicht kollidieren,
nehme ich einfach das Ausrufezeichen und dann kollidieren sie.
Und diese Zusammenhänge sind, glaube ich, mathematisch relativ einfach
zu erfassen. Also wir haben ja hier unser X,
machen wir es mal wieder schwarz.
Hallo, dann mache ich die Farbe. Schwarz ist alles
auf Null. Genau, manchmal ist es ein kleiner.
Also hier ist ja quasi meine Position,
ich nenne die jetzt mal P, hier ist die andere Position.
Und wie komme ich denn jetzt an die Position dieses Punktes
quasi ran?
Ich glaube, die Position ist zu zweit. Genau. Also,
wenn ich sage, wenn die Position plus die Breite kleiner oder
gleich diese Position ist, dann habe ich kein Problem.
Dann ist die eine Linie links von der anderen Linie.
Ja, Position sozusagen immer ausgedrückt. Die Position ist immer,
richtig, so wie wir es programmiert haben,
ist das immer links, beziehungsweise oben, je nach Dimension.
Ja, genau. Und das ist also der einfache Fall.
Und der andere Fall ist genauso einfach nur umgedreht. Also,
ich glaube, das müssen wir nicht mal von Hand programmieren.
Das können wir doch mal vielleicht als kleine Hilfsmethode machen.
Also, ich könnte doch zum Beispiel sagen, ist Leftoffline-Segment over.
Und ich scrolle das mal hoch. Meistens ist das
unten am Beamer immer nicht so schön. So,
also ich will jetzt eine Methode schreiben, die feststellt,
ob ich selber links bin von diesem anderen Line-Segment.
Und das wurde mir gerade gesagt, wie das logisch ist.
Ich programmiere das jetzt einfach nur. Also,
wenn meine Position, plus meine Größe,
kleiner oder gleich die Position von dem anderen Line-Segment ist.
Das haben wir gerade uns grafisch klargemacht, ja.
Es fehlt ein Return-Statement. Oh, Dankeschön.
Der Typ fehlt, ne?
Genau, Dankeschön
Das haben wir uns gerade grafisch klar gemacht.
Und jetzt muss ich diese Methode hier ja nur noch benutzen.
Versuche ich das nochmal. Also ist Left of Other.
Damit prüfe ich jetzt den oberen Fall, ob ich selber
links von dieser Linie bin. Aber ich würde jetzt ja
auch gerne prüfen, ob diese Linie links von mir ist.
Brauche ich dafür jetzt eine eigene Methode oder gibt es schon
eine Methode, die für zwei Linien prüft,
ob die eine links von der anderen ist?
Ja. Ich möchte einfach nur die beiden verzerrten und fertig.
Okay, also ich könnte sagen, hey,
du andere Linie,
bist du denn links von
Tja, was schreibe ich denn jetzt hier rein?
Ich will jetzt ja sagen, ich selber sozusagen.
Gibt es in Jabba irgendwie die Möglichkeit zu sagen,
das Objekt, ich selbst, wer hat heute noch nichts,
tue das noch nichts.
Wiss, genau. Oh, und jetzt muss ich es noch negieren.
Hafts hätte ich fast vergessen. Also das ist so,
ne? Also wenn es nicht der Fall ist,
dass ich links von der anderen Linie bin,
ist das und jetzt richtig?
Oder muss das ein Oder sein? Muss das ein Oder sein?
Ich glaube ja, ne? Puh, das probieren wir
gleich mal. Wenn es nicht der Fall ist,
dass ich links von der anderen Linie bin oder die anderen Links von mir,
dann müssen wir kollidieren.
Andere Möglichkeiten gibt es nicht
Puh. Aber? Man kann ja, man kann ja
jetzt nicht lang über das oben drüber in die Blocks.
Das heißt, dass man hier dann doch irgendwie diese Exposition gegeben hat,
kann man noch. Richtig. Wir haben das jetzt
nur für eine Dimension gelöst. Wir haben so getan,
als wäre die Welt eindimensional und da gibt es nun mal
diese Kollision in der zweidimensionalen Welt, müssen wir jetzt eben beachten,
dass es zwei Dimensionen gibt.
Und darauf kommen wir jetzt. Sehr gut. Das ist,
ja, ich glaube, es muss auch bei uns sein,
wenn du hier noch eine Klammer bist.
Okay. Wie ist das erste Ruder nicht?
Das ist ja total spannend. Also wir gucken nochmal
ganz kurz
Wenn da ein Unt stehen würde, dann würde ich ja prüfen,
dass diese Linie links von dieser und rechts von dieser ist.
Das erscheint mir irgendwie sinnlos. Diesen Fall kann es eigentlich
nicht geben. Also deswegen bin ich eigentlich ziemlich sicher,
dass es ein Oder sein muss.
Aber wir werden das gleich sehen. Okay,
wir haben das jetzt also für eine Dimension gelöst,
dann gehen wir jetzt mal in eine Abstraktionsebene höher.
So. Gut. Wir erinnern uns, eine Box besteht ja
aus zwei Line-Segments, einmal horizontal, einmal vertikal.
Für jedes Line-Segment gibt es jetzt eine Operation,
die mir sagt,
ob Kollisionen vorliegen oder nicht
Wie kann ich das jetzt sinnvoll aufrufen,
sodass es für beide Dimensionen geprüft wird?
Du hattest, glaube ich, schon eine Idee, oder?
Ja, ja. Punktzentrale aufnehmen, weil wir ja bis
links geguckt haben. Okay, also ich frage quasi das
horizontale Landsegment, hey, kollidierst du?
Mit was? Was muss ich da jetzt reinschreiben
in die Klammern?
Genau. Other, Punkt, Horizonte,
denn sonst wäre es ein Typfehler. Horizontal. Ja,
also kollidiert meine horizontale Komponente mit der anderen heuzontalen Komponente.
Ich habe mich irgendwo vertippt, oder? So,
und jetzt kommt wieder die spannende Frage, was für ein Operator muss hier hin?
Und dann muss ich das auch für die vertikale Komponente prüfen.
So, ne? So. Schauen wir uns wieder das Spiel an.
Aber ich kann es jetzt nicht übersetzen, wegen diesem blöden Operator.
Ich muss das einmal auskommentieren. Dass wir uns die Frage stellen,
muss da jetzt ein und oder ein oder hin?
Also du hattest ja schon wunderbar festgestellt,
Wenn wir nur die horizontale Komponente prüfen, dann wird er,
wenn ich hier versuche, rüberzugehen, wird er sagen,
das geht nicht.
Oh. Hätte ich jetzt zumindest erwartet. Das ist ja spannend. Ah,
ich habe das in der obersten Abstraktionsebene noch nicht eingebaut.
Das machen wir vielleicht mal zuerst. Ich springe ja ein
bisschen zwischen den Ebenen hin und her. Ich hoffe,
das stört euch nicht. Also momentan behaupte ich ja,
dass der Spieler nie in ein Hindernis reingelaufen ist.
Schauen wir uns mal den Zustand dieser Klasse an.
Also wir haben eine Spielerbox, eine Obstical 1 Box,
eine Obstcircle 2 Box und eine Obstcircle 3 Box.
Und alle diese Boxen können mir die Frage beantworten,
kollidiert diese Box mit dieser Box?
Wie kann ich das jetzt
sinnvoll aufrufen
Man muss sich irgendwie prüfen, dass die Obstacles miteinander kollidieren oder...
Man denkt immer auf der Spieler, die Obstacles.
Genau. Also, hey, lieber Spieler.
Cool, nice. Kollidierst du. Ich beschränke das
jetzt erstmal auf das erste Obstacle, ja?
Ich frage ihn, ob er mit dem ersten Obstacle kollidiert.
Okay. Das müsst ihr jetzt dafür sorgen,
dass ich unmöglich über diese erste Hürde rüberkomme,
weil ich ja horizontal kollidiere.
Ja. Gut. Jetzt kommen wir wieder in die
mittlere Abstraktionsebene. Ich muss es ja für beide Dimensionen prüfen
Die Frage ist nur, muss jetzt hier ein
Und oder ein Oder rein? Also gibt es eine Kollision,
wenn mindestens eine Kollision in dieser oder dieser Ebene stattfindet oder
müssen sie in beiden Ebenen stattfinden?
Wer ist dafür, dass dein Oder hin muss?
Das sind so vielleicht ein Dutzend Leute. Wer meint,
dass es ein Und sein muss? Deutlich mehr. Ich
glaube auch, dass es ein Und sein muss,
weil es muss ja unwahrscheinlicher werden, je mehr Dimensionen dazukommen.
Schauen wir mal. Ich müsste jetzt
hier rüberkommen können
Ja, sehr gut. Und das ist also kein Problem.
Soll ich jetzt mal reinlaufen und gucken, ob das noch geht?
Ich laufe mal von hier raus rein. Ja. Tatsache
. Das ist doch nicht schlecht. Und jetzt schaue ich
noch mal ganz kurz, wenn ich hier so rüber laufe.
Und jetzt, ja, woran liegt das denn jetzt?
Warum klappt das denn nur für das erste Obsttückel?
Ja. Du hast eben noch das erste gekomplett.
Richtig, hier, ne? Okay, das heißt,
ich mache wieder so ein bisschen Copy-Paste.
Vielleicht meine eigene Zeilen. Und jetzt stellen wir uns natürlich
die Frage, wenn man Copy-Paste,
muss man
auch was ändern
Was für Operatoren müssen jetzt hier hin? Also,
muss ja jetzt stehen, der Spieler kollidiert mit allen Dreien
oder mindestens eine. Überleg mal wieder ganz kurz,
soll da ein unten oder soll da ein oder hin?
Ich finde das toll, dass wir das bulische Allgemeine
jetzt hier schon wieder so an einem praktischen Beispiel wiederholen.
Also, wer glaubt, dass da ein oder hin muss?
Ja, das sind ziemlich viele, so 50 Leute oder so.
Wer glaubt, dass es ein und sein muss?
Oh, gar keiner. Gut. Denn man liest das Ode
ja immer als mindestens ein und tatsächlich hat der Spieler verloren,
wenn er mindestens eine Hürde zurzeit damit kollidiert.
Also ansonsten, er kann ja nicht mit allen Dreien
gleichzeitig kollidieren,
das wäre irgendwie Schwachsinn
Okay. Dann spiele ich das nochmal. Also. Wenn
ihr entsprechend groß wäre, genau. Vielleicht wäre das dann
das Ziel des Spiels mit allem zu kollidieren.
Weil das dann so schwer ist. Also ich komme jetzt
hier rüber. Und jetzt, das ging ja vorher nochmal,
mal gucken. Genau, das wird jetzt also erkannt.
Und dann machen wir dasselbe nochmal hier. Mit dem dritten,
mit der dritten, mit dem dritten Opsical.
Dass ich da rein laufe, wird also jetzt auch erkannten.
Jetzt macht es ja schon fast Spaß zu spielen.
Okay. Gut. Also dann, ich würde das nochmal
ganz kurz zusammenfassen. Wir haben ja kaum noch Zeit
Wir haben uns also an dieser Stelle Gedanken darüber gemacht,
wie kann ich mathematisch ausdrücken, dass zwei Linien miteinander kollidieren,
dann haben wir festgestellt, hey, man dreht das einfach um,
die Nicht-Kollision ist deutlich einfacher festzustellen,
das mache ich hier quasi für ein Pärchen,
habe ich diese Methode geschrieben,
da muss ich sie einmal so rum aufrufen und einmal so rum aufrufen,
haben wir ja immer die schöne Wiss-Referenz kennengelernt.
Nachdem das funktioniert hat für ein Segment,
haben wir das quasi in zwei Dimensionen gehoben, wir haben gesagt,
es muss sowohl in der horizontalen als auch in der Vertikalen,
muss es kollidieren, sonst ist es keine Kollision.
Und dann haben wir in dem eigentlichen Spiel gesagt, wunderbar,
das suchen wir auch wieder auf und verknüpfen das mit diesem Operator,
weil man mit mindestens einem Obst kollidieren muss, damit man verliert.
Okay, den Rest des Quelltextes findet ihr unten,
wer Lust hat, kann sich das angucken,
müsst ihr aber auch nicht.
Vielen Dank