Ja, herzlich willkommen zur fünften Vorlesung von SE1. Wir
sind jetzt hier am Ende einer Stufe,
bevor ich jetzt so ein bisschen inhaltlich werde,
möchte ich ein bisschen was mit Storesi machen.
Ich habe nämlich eine neue Version bekommen, noch minimal anders.
Es ist ganz lustig, was jetzt so passiert hier.
Also es gibt tatsächlich dann auch Teilnehmer,
die jetzt angefangen haben, das Ganze zu hacken.
Ja, also tatsächlich jetzt, wir haben Abstimmungsergebnisse bekommen,
die irgendwie gefälscht waren.
Wir haben herausgefunden, dass manche Leute hier nicht nur eine,
sondern 20 Stimmen abgeben.
Das kann man
alles machen
Wenn man ein bisschen die Technik kennt, die wir da im Hintergrund laufen haben.
Kann man gern machen. Ist ja auch gut. Das
ist ja für uns hier auch ein Test dieser Software.
Es hat ja so zwei Sinne. Einmal möchten wir die
Software einsetzen und dadurch verbessern. Zum anderen will ich natürlich
auch einfach probieren, ob das hier ein gutes Instrument ist.
Und das möchte ich ein bisschen mit euch auch rauskriegen.
Deswegen jetzt erstmal hier eine Abstimmung, die ich mal eben ausprobieren will.
Und zwar möchte ich gerne, oh, oh,
oh, oh, free ist mal wieder, oh,
freeze, freeze.
Ja, also, das ist die erste Frage,
die ich stellen will heute zum Einstieg
Diesmal ein bisschen leichter eingeschränkt. Also ich möchte nur wissen,
wer ist im Hörsaal und dann entweder mit einem Clicker
oder mit Smartphone Laptop, was weiß ich immer.
Oder wer nimmt außerhalb des Hörsaals teil. Es gibt ja Leute,
die den Livestream sehen und möglicherweise auch mit abstimmen.
So, das würde mich jetzt einfach interessieren. Der Livestream scheint
noch nicht sichtbar zu sein, zumindest auf dem Laptop da vorne.
Aber da läuft er. Gut. Also wir werden es
ja jetzt sehen. Wenn ich jetzt in der Abstimmung stimmen
kriege, die sagen, ich nehme von außen teil.
Ich lasse das mal loslaufen hier. Oh, stopp mal
eben. Ich wollte nochmal eben A,
ich mache nochmal einmal den Barcode,
den sollte ich nochmal eben
ganz kurz zeigen
Der ist nochmal für die Leute,
die ich jetzt mit einem neuen Smartphone da sitzen,
dass sie ihn nochmal eben ganz kurz abfotografieren können.
Hier der QR-Code. So, das sollte erstmal reichen.
Und dann starte ich hier die Abstimmung nochmal weiter,
also lasse sie weiterlaufen und dann sammeln wir mal so ein bisschen Stimmen und ich bin einfach gespannt,
ob tatsächlich Leute da sind, die,
also ob Leute nicht da sind,
die aber trotzdem teilnehmen.
Das wäre ganz interessant,
das festzustellen
Gut. Naja. Das Gemeine an diesem,
an diesem Sturesi ist auch, dass man ziemlich deutlich sieht,
wie viele Studierende hier sind, mehr oder weniger.
Also im Laufe des Semesters wird das ja mit nach unseren Erfahrungen weniger.
Und in den letzten Vorlesen wird man dann schwarz auf weiß sehen,
wie viele Leute noch da sind. Ich weiß nicht,
ob das so gut ist, aber na gut.
Ihr seid ja noch relativ zahlreich da, zum Glück.
Gut. Das sind relativ wenige Stimmen. Ich gucke jetzt
mal. Es kann nämlich jetzt tatsächlich sein, doch,
das sieht gut aus.
Oh, okay
Und wenn das jetzt ernsthaft abgestimmt war, ich hoffe das ja,
das ist ja keiner hier gezwungen, die Wahrheit zu sagen,
dann haben wir tatsächlich eine relativ ausgeglichene Teilnehmerzahl.
Das sind ungefähr 60 Leute hier im Hörsaal mit einem Smartphone-Laptop
, 60 Leute mit einem Clicker.
Und 60 Leute ungefähr irgendwie außerhalb des Hörsaals.
Bei 180 Stimmen, ja, kommt das ungefähr hin.
Sehr schön. Dann würde ich noch eine nächste Frage stellen wollen.
Und zwar habt ihr möglicherweise gar keine Lust mehr darauf.
Das heißt, wenn ihr jetzt sagt, dieser ganze Storysi-Kram,
der geht mir voll auf die Nerven,
das bringt gar nichts für die Veranstaltung,
das lenkt nur ab
Dann könnt ihr das jetzt auch zum Ausdruck bringen.
Ich will so ein bisschen, dass es davon abhängig machen,
ob wir das jetzt weitermachen.
Also wenn jetzt hier eine überwiegende Mehrheit sagt, nee,
wir wollen das nicht, dann werden wir es einfach sein lassen.
Also ich will ja hier niemandem das aufzwingen,
aber ich habe so den Eindruck, dass es interessante Möglichkeiten bietet.
So, das sind jetzt auch wieder so ungefähr 180 Stimmen,
das sieht gut aus.
Es werden auch immer so im Verlauf der Veranstaltung
ein bisschen mehr
Das war beim letzten Mal auch so, ich halte das mal an.
Wir gucken uns das mal an. Wir blenden durch.
Okay, das ist ein ziemlich eindeutiges Votum.
Ich würde sagen, dann machen wir weiter mit Sturesi.
Und dann kann ich auch weitermachen mit der Vorlesung.
Gut, das zum Einstieg. Dann werde ich in SE1
in dieser Vorlesung immer so zu Anfang, nicht immer,
aber häufig zu Anfang, so ein paar Worte vorneweg sagen.
Das sind manchmal Hinweise, manchmal sind das so Ermahnungen mit
dem erhobenen Zeigefinger.
Das ist erstmal
nur eine Info
Wir haben ja den zweiten Teil des Folienskriptes. Jetzt seit
letztem Donnerstag in den Übungen verteilt. Das heißt also,
theoretisch könnt ihr alle da mit einem ausgedruckten Skript sitzen.
Das ist auch eigentlich der Plan, dass wir es immer
so rechtzeitig rausbringen. Das klappt nicht immer so,
weil wir auch nicht so die volle Kontrolle über den Druckprozess haben.
Aber das läuft. Was ich jetzt leider sagen muss,
ist, dass ich nicht garantieren kann,
dass der dritte und der vierte Teil euch auch noch ausgedruckt zur Verfügung gestellt werden kann,
weil wir ein Limit bekommen haben, einen Stopp.
Wir dürfen vom Fachbereich aus nicht mehr Skripte und ähnliches drucken.
Ich weiß nicht, ob diese Meldung, die vor zwei Wochen rumging,
für das laufende Semester gilt oder für die Zukunft.
Ich bin da noch unsicher, ich werde das nochmal nachfragen.
Ich bin eigentlich der Meinung, wenn wir damit jetzt angefangen haben,
wäre es ziemlich blöd, wenn wir es nicht weitermachen,
aber das kann ich euch noch nicht hundertprozentig versprechen.
Gut, dann ist es so, ihr wisst,
in den Übungen sollt ihr ja möglichst konzentriert mitarbeiten.
Wir haben ja so ein gewisses Tempo,
alle müssen das gleiche Tempo gehen, das kann man didaktisch kritisieren,
aber wir versuchen halt irgendwie hier alle so in einem bestimmten
Rhythmus durch die Inhalte zu führen.
Und da ist es so, dass ihr jetzt inzwischen,
wir sind jetzt in Woche fünf, also morgen fängt Übungswoche fünf an.
Das heißt, Übungswoche drei sollte jetzt abgenommen sein.
Das dritte Aufgabenblatt
Wer das nicht hat, sollte mächtig nacharbeiten.
Es gibt einige Leute, die sind später eingestiegen.
Das ist ziemlich anstrengend. Später das Semester einzusteigen,
weil wir dann ziemlich viel nacharbeiten muss.
Das meinen wir schon ziemlich ernst. Wir werden dann auch
relativ deutlich dann Mails verschicken, wenn wir den Eindruck haben,
dass wie man sehr weit zurückhängt und so weiter.
Meistens bleiben die Leute aber weg,
weil sie einfach aus persönlichen Gründen nicht mehr studieren oder ähnliches.
Gut. Dann E-Mail-Adressen, wir nehmen Comsi eingetragen seid.
Einige haben da irgendeine E-Mail-Adresse eingetragen, die sie nie lesen.
Das ist nicht so schlau. Wir schicken ja auch ab
und zu mal Informationen über das Comsi per Rundmail.
Da wäre es schon schlau, wenn eure E-Mail-Adressen da zum einen
gültig sind und zum anderen auch von euch regelmäßig gelesen werden.
Also das nochmal überprüfen vielleicht. Muss nicht jetzt sein,
ja. Ich meine, einige haben ihren Rechner ja dabei.
Gut, dann gibt es ein Tutorium. Das heißt,
es gibt jetzt eine Veranstaltung, die Inhalte wiederholt.
Das ist sehr viel interaktiver als die Vorlesung.
In der Vorlesung versuche ich, interaktiv zu sein,
aber meistens stehe ich ja doch hier vorne und erzähle einfach was.
Im Tuturm ist das ganz anders. Da könnt ihr tatsächlich,
da ist auch jemand vorne, nämlich Sascha und beantwortet Fragen.
Und dann wird irgendwie auch ein Laptop dabei sein. Das heißt,
man wird relativ schnell mit Blue Jay was machen können,
man wird was ausprobieren können.
Ihr könnt also ganz viele Fragen stellen und versuchen,
mit ihm auch Inhalte zu klären
Sein Konzept, was wir schon seit Jahren haben,
was auch sehr erfolgreich ist. Das solltet ihr wahrnehmen,
wenn ihr das Gefühl habt, dass ihr mit dem Tempo,
was wir hier haben, nicht so gut mitkommt.
Das ist ein Angebot für diejenigen, die da einfach noch
ein bisschen mehr Diskussionsbedarf haben. Gut, und dann,
ja, wir haben euch durch vier Wochen,
vier Aufgabenblätter vier Vorlesungen durchgejagt und alles,
was bisher dran war, müsst ihr sicher beherrschen jetzt.
Also das klingt so blöd, aber wir machen jetzt einfach weiter.
Wir bauen auf dem auf,
was wir bis jetzt erzählt haben und es ist tatsächlich so,
wenn ihr Schwierigkeiten hattet mit den Begriffen,
dann wird das nicht
weniger werden
Das kumuliert sich leider. Dieses Nichtwissen über die Begriffe und Konzepte. Und deswegen,
wie gesagt, empfehlen wir ja auch immer,
macht ein Glossar, wenn ihr irgendwie mit diesen wirklich vielen Begriffen,
die wir euch um die Ohren gehauen haben, nicht so gut klarkommt.
Es ist zumindest, wie ich finde, alles passend zueinander.
Es ist nur viel Zeug. So ist das. Okay. Ja,
und wenn ich das jetzt sage, Begriffe,
dann kann man sich jetzt nochmal hier so ein bisschen angucken,
was haben wir denn bis jetzt gemacht?
Also wir sind jetzt am Ende von Stufe 1, am Anfang von Stufe 2.
Das heißt hier, der Nebel vor uns lichtet sich langsam.
Wir haben jetzt gerade so hier eine Stufe geklärt.
Das sind alles Begriffe, die ihr jetzt kennen sollt.
Klasse Objekt, Methode, Parameterfeld, variable Sequenz. Zuweisung,
Ausdruck, Syntax in EBNF, bedingter Anweisung, primitiver Typ.
Solltet ihr irgendwie mal gesehen haben, was mitgemacht haben,
solltet ihr einordnen können und noch ein paar mehr Begriffe.
Das waren die ersten vier Wochen. Was wir gemacht haben,
war, ihr habt gelernt, dass Objekte,
Exemplare von Klassen sind, dass die einen Zustand haben,
dass diese Zustände in Feldern gehalten werden,
dass in den Methoden, die wirklichen Aktivitäten stattfinden,
in den Methoden stehen, Anweisungen bestehen,
entweder aus Zuweisungen oder aus Methoden aufrufen.
Dabei kommt es dann zu Parameter auf, Parameterübergaben,
wenn man eine Methode aufruft.
Es können Ausdrücke da stehen, da sind primitive Typen involviert.
Das ist mal eben der Abriss von Level 1.
So, jetzt kommen wir zu Level 2. Da wird es
jetzt ein bisschen klarer, was wir jetzt machen.
Jetzt kommen wir wirklich ein Komplexitätsschritt. Das heißt,
jetzt werden wir explizit ansprechen, wie das ist,
wenn Objekte, andere Objekte benutzen.
Ihr habt das schon teilweise gesehen in dem Zeichnerprojekt.
Das werden wir uns jetzt ein bisschen systematischer ansehen.
Das geht es also tatsächlich um den Begriff der Referenz,
der in Java sehr speziell ist.
Das Konzept, das Konzent hinter einer Referenz in Java,
ist natürlich allgemeingültig. Fürlich, für alle Programmiersprachen,
für alle im parativen Sprachen, für alle de.
Die heißende, in heißens, die Referenzen.
Die Referenz in C plus, das ist etwas anderes.
Das muss man wissen. Da muss man wissen. N nicht,
dass man irgendwie glaubt, dass wir das d,
dass der gleiche, begriffe.
Das de. Das ist. Das ist. Das
ist lot, die Referent, d. drat.
Das ist das de ät, was dahinter.
Das ist, de de lot,
d dran
d drat
Andere ist es eigentlich so, haben wir festgestellt,
ohne das Verständnis von Referenzen eigentlich nicht ernsthaft in Jara programmieren kann.
Das heißt, wer Referenzen nicht verstanden hat, wird nie ein guter Jara-Programmierer.
Ganz banal. Gut. Soviel jetzt zum Auftakt, was
jetzt auf uns zukommt. Ich will das Ganze jetzt,
in der ersten Hälfte will ich was über Referenzen erzählen.
Das heißt, ich erläutere, was eine Referenz ist.
Dazu werde ich ein bisschen was sagen, was ein Typ ist.
Also erstmal so ein bisschen nochmal aufgreifen, diesen Typbegriff,
den ich ja schon mal hier so informiert eingeführt habe.
In der zweiten Hälfte schauen wir uns dann
die UML an
Weil die UML eine schöne Möglichkeit ist, so Objektsysteme zu visualisieren.
Und da sind die Referenzen dann auch wieder sichtbar.
Okay, also, was wir bis jetzt gesehen haben,
sind die elementaren Datentypen. Jetzt gucken wir uns an,
wie das mit den Benutzer definierten Typen aussieht. Okay,
der Typbegriff, erste Definition, ja, okay,
im Informatik-Duden findet ihr sowas unter einem Datentyp,
vertitt man die Zusammenfassung von Wertebereichen und Operationen zu einer Einheit.
Das trifft es ziemlich gut. Das habe ich auch letzte
Woche schon erzählt. Ein Typ könnt ihr euch merken,
ist eine Wertemenge auf der Operation definiert sind.
Das ist zusammen gebündelt
Letztes Mal habe ich schon erzählt, so was wie Int,
da gibt es die Wertemenge von minus zwei Milliarden bis plus zwei Milliarden.
Und es gibt Operationen. Und ich habe auch letzte Woche erzählt,
da muss man eigentlich genauer jetzt sagen,
das ist die ganzzahlige Addition, ganzzahliges Subtrahieren und so weiter,
weil das ist ja der Datentyp Int.
Es gibt ja auch noch einen anderen Datentyp,
Float oder Double in Java zumindest. Da sind das andere
Operationen, die zufällig mit dem gleichen Operator geschrieben werden.
Das heißt, wir unterscheiden ja die Operationen von den Operatoren.
Puh, ganz schön gemein. Vambul ist das ein bisschen einfacher,
da gibt es eigentlich nur eine Wertemenge mit zwei Elementen,
nämlich die Werte war und falsch
Die Wahrheitswerte und dann gibt es die Operation,
die ja auch in den Übungen teilweise kennengelernt habt und oder exklusiv oder nicht Verneinung.
Und das ist tatsächlich immer das gleiche Spiel.
Man hat irgendwie eine Wertemenge, also irgendwie Elemente,
die in einer Menge sind und man kann irgendwie Operationen darauf anwenden.
Meistens kommt auch wieder was aus derselben Menge raus.
Nicht immer, ich kann ja auch Ins zum Beispiel vergleichen,
ist der größer als der und als Ergebnis kommt ein Bulien raus.
Das ist, wie gesagt, zentral.
Typ, Wertemenge plus Operationen. Warum machen wir das?
Also warum sind Typen so wichtig? Naja,
weil ihr jetzt mit Java arbeitet
Und Java, eine der Sprachen, ist, die euch statische Typisierung abfordert.
Das heißt, wenn ihr ein Java-Programm schreibt,
müsst ihr ja bei allen Variablen deklarieren, von welchem Typ sie sein sollen.
Das ist sehr nützlich, aber es ist nicht zwingend notwendig. Es gibt Programmiersprachen,
wie zum Beispiel Smalltalk, da ist das so,
wenn ihr eine Variable benutzen wollt,
mit der ihr irgendwie Objekte manipulieren wollt,
dann müssen die nicht typisiert werden, indeklariert einfach eine Variable und dann,
die hat einen Namen, keinen Typ,
nur einen Namen und dann kann man da irgendwie auch eine Referenz zuwarten auf ein Objekt und dann kann man das Objekt manipulieren und dann
Da kann man eine Referenz auf ein anderes Objekt bekommen.
Also das geht da sehr viel dynamischer. Und die Leute,
die Smalltalk programmieren, sagen, das ist prima.
Super. Es gibt aber auch durchaus eine Richtung in der Softwareentwicklung oder in der Softwaretechnik,
die sagen, also so statisch-typisierte Sprachen, so wie Java,
C-Sharp, C plus Pascal-Eifel, also die Sprachen,
mit denen wir hier überwiegend umgehen.
Dass da diese Typ-Prüfung mit drin ist, das ist gut.
Also ich kann das auch noch mal wie immer in BlueJ zeigen.
Ich hoffe mal, ich habe jetzt hier das richtige Projekt
gerade geöffnet
Das Projekt Zeichner ist eigentlich auch erstmal egal.
Ich kann ja hier eine Direkteingabe jetzt irgendwie sowas hinschreiben,
wie oft dieser Folie steht,
also zum Beispiel da unten steht 12 plus 6. Dann ist es einfach so 12 plus 6 ist ein Ausdruck,
das wisst ihr, zwei Operatoren, ein Operator,
der definiert die ganzzahlige Addition und dann kommt da 18 raus,
klar, aber es steht auch dabei, es ist ein Int.
Und das ist ganz wichtig,
in jedem Dava-Programm könnt ihr bei jedem Ausdruck erkennen,
welcher Typ der hat, welchen Typ der so Ausdruck hat.
Das könnt ihr ablesen, da seid ihr noch nicht so geübt.
Der Compiler kann es aber auch und das ist ganz entscheidend,
weil der Compiler kann euch dann auf die Finger klopfen,
wenn ihr was Falsches zu machen versucht
Also, was hier jetzt steht, 12 plus Falls,
das geht einfach nicht. 12 plus Falls, da sagt
jeder Compiler, jeder Java-Compiler, das geht so nicht.
Bad Operant for Bad Operant Types for Binary Operator Plus,
first type in second time Bulli.
Da sagt er einfach, das geht nicht.
Ich kann nicht irgendwie, ich sehe keine Operation,
die ein Int mit einem Bullien addiert.
Das ist gut, weil man dann tatsächlich Hinweise vom Compiler
bekommt, was man falsch gemacht hat.
Und oft vertippt man sich einfach auch.
Von daher ist das
wirklich hilfreich
Wie gesagt, das muss nicht so sein,
aber wir bringen es euch jetzt hier erst mal so bei.
Und dann müssen wir halt noch mal so
ein bisschen uns verdeutlichen, warum das so gemacht wurde.
Eine andere Motivation. Also das eine ist Typen,
man kann sozusagen tatsächlich, wenn man einen typisierten Programmtext hat,
immer gleich erkennen, welcher Typ ist denn das?
Zum anderen ist es so, dass ihr euch klar werden müsst,
dass die Idee eines Typs völlig zentral ist für die Programmierung.
Nämlich, wenn man sich überlegt,
ich habe letztes Mal erzählt oder vorletztes Mal,
in der imperativen Programmierung machen wir hier sehr viel mit der Idee,
dass wir auf dem Verneumann-Rechner aufsetzen. Das heißt,
letztendlich haben wir einen großen Speicher und wir haben einen Prozessor,
der irgendwie auf diesem Speicher irgendwie dachten, lesen kann,
Daten schreiben kann und irgendwie Befehle von aus dem Speicher holt.
Und dieser Hauptspeicher, auf dem wir eigentlich konzeptuell durchgängig arbeiten,
besteht einfach aus sehr vielen Zellen gleicher Größe,
heutzutage 32 oder 64 Bit groß und durchgehend adressierbar.
Und da stehen irgendwelche Binärcodes drin. Das ist auch wieder
nur eine Visualisierung, also ein Modell, was wir haben.
Natürlich stehen da nicht nur einen Einzelnen im Hauptspeicher.
Da sind irgendwelche elektronischen Bauteile in bestimmten Zuständen und das interpretieren wir als 0 und 1.
Das ist sozusagen die erste Stufe sozusagen. Über der Hardware
sagen wir, das ist 0 und das ist eins.
Das ist einfach so definiert und dann kann man sich so
einen Speicher so vorstellen.
Da stehen also lauter 0 und 1 drin
So, wenn ich jetzt aber auf sowas draufdrücke,
keiner von euch wird mir sagen können, was das bedeutet.
Das kann ich erst, wenn ich die Typbrille aufhabe.
Deswegen habe ich auf der vorigen Folie diese Brille drauf gehabt.
Ich schaue drauf und sage, naja gut, diese Bits hier,
diese 32 Bits, die fasse ich jetzt mal auf,
als hier Daten als ein Datum.
Zum Beispiel kann das eine ganze Zahl sein. Im Zweierkompliment in Java. Dann weiß ich genau,
die Bits haben eine bestimmte Stelligkeit im Zweier, im System,
im Zweierpotenzen und dann kann ich das hier irgendwie aufaddieren und kommen dann irgendwie auf den Wert und weiß dann,
aha, wenn ich das als interpretiere,
also wenn der Typ dessen,
was da steht,
in ist,
dann hat es
den Wert
Gleiche Bitmuster, kann völlig andere Bedeutung haben,
zum Beispiel als Werkkammer zahlen. Das ist das gleiche Bitmuster.
Es kommt also darauf an, wie ich drauf gucke.
Das ist auch so ein ganz grundlegendes Konzept von Typisierung.
Ich typisiere den Speicher, das geschieht auf einer höheren Ebene,
auf der untersten Ebene ist es einfach flach, ein einziger Urwald von 0 und 1.
Und dann müssen wir einfach Abstraktionsstufen drüberlegen. Was wir halt machen,
ist, dass wir auch zum Beispiel bei Programmen dann wissen,
naja, das ist wahrscheinlich irgendwie ein Befehl im Programmtext,
der irgendwie dafür sorgt, dass ein Register geladen wird oder sonst irgendwas.
Das ist ganz wichtig. Und ich will jetzt nochmal so
ein bisschen das auch nochmal, sagen wir,
Auf solidere Basis stellen, was ich hier erzählt habe,
weil es nämlich ein Typbegriff gibt,
den hat der gute Herr Horror vor etlichen Jahren mal geprägt.
Und auch den beziehen wir uns hier immer noch.
Und dieser Artikel ist hier so ein bisschen gleich wiedergegeben auf der nächsten Folie.
Den gehe ich mal so ein bisschen systematisch durch.
Bei Typen spricht man auch gerne von Datentypen in der Informatik,
weil ja irgendwie sich immer auf Werte bezogen wird.
Also irgendwie wird ja gesagt, wie ein bisschen wir
Dinge als Werte interpretiert werden.
Und Werte stellen letztendlich Daten da und Daten sind das,
was wir dann mit den Datentypen
auch modellieren wollen.
Auch da wieder wichtig, jeder Wert gehört genau zu einem Datentyp,
das habe ich letztes Mal auch gezeigt, ja,
null, ist in null.0, ist Float und so weiter,
nee, Double und so weiter.
Das heißt also, jeder Wert hat erstmal schon mal gehört zu einem festen Datentyp. Gut,
jetzt nochmal hier dieser Text von Tony Hawk,
das klingt jetzt alles ganz wild, ich will das,
aber wir gehen das Ganze in Ruhe durch,
type determines the class,
of that is which maybe as you by a very bit orys pression.
Das heißt also, ein Typ definiert eine Menge von Werten,
die eine Variable einen auch so annehmen kann.
Also ganz wichtig, ein Typ eine Wertemenge. Und zwar die Werte,
die eine Variable oder einen Ausdruck annehmen, muss man unterscheiden.
Die wissen ja, es gibt so Variablen,
die können so Werte halten oder ein Ausdruck kann auch
einen Wert haben
Jeder Wert gehört genau zu einem Typ, das ist ganz wichtig.
Und die Typinformation ist statisch aus dem Quelltext ermittelt,
was habe ich vorhin gezeigt? Ich kann direkt ablesen,
welchen Typ einen Ausdruck hat oder eine Variable.
Operatoren sind auch getypt, das haben wir auch gesehen.
Ich kann ja zum Beispiel sagen, drei plus fünf,
dann ist es eine Interger-Addition. Wenn ich schreibe,
hallo, plus Welt, dann kommt da hallo Welt raus,
dann ist es der gleiche Operator, aber eine andere Operation.
Das eine ist die String-Konkretation, zwei Zeichen kennen werden verkettet,
das andere ist eine Intedition
Die Operatoren sind also getypt, auch teilweise abhängig von dem Operanten,
die drumherum stehen. Aber zum Beispiel der Operator und dieser
und und Operator für logisches und erwartet einfach zwei Bullshow-Apparanten.
Das geht gar nicht anders. Dann ein Typ definiert Operationen,
das haben wir jetzt mehrfach gesagt, also einfach die Dinge,
die man damit machen kann mit so diesen Elementen aus der Wertenmenge.
Und diese Typinformation schützt und legt Semantik fest. Also zum einen
wird überhaupt erstmal klar, was man damit machen kann.
Also wenn ich zum Beispiel da eine Invariable habe,
dann kann ich die halt addieren,
aber ich kann da nicht irgendwie eine Operation dran aufrufen.
Ich kann jetzt nicht sowas schreiben wie 2.Kett,
Get Get irgendwas und dann irgendwie noch so.
Also ich kann an der 2 nicht jetzt mit einer Punktnotation eine Operation aufrufen.
Das sind die Operationen, die ich da nicht zur Verfügung
habe, eine Methode. Legt also auch fest,
was man machen kann mit den Elementen und schützt uns.
Das ist das Hauptargument für solche statischen Typisierungen. Und dann
hat er am Ende noch was gesagt, the types in
which we are interested others already familia too mass maticians.
Also kathesische Produkte, Mengen, Funktionen und so weiter.
Das würde ich sagen, kann man heute
stark relativieren
Also in den 70er Jahren war das eine verbreitete Sichtweise auf Programmieren.
Das ist eigentlich eine Fortsetzung der Mathematik ist. Heutzutage sind wir da
deutlich weiter. Also wir modellieren inzwischen so viele Dinge in Software,
die gar nicht so viel mit Mathematik zu tun haben.
Und das ist auch gut so,
weil wir ja irgendwie Probleme lösen wollen in dieser Welt und
diese Probleme dieser Welt sind nicht alles mathematische Probleme.
Gut, also das ist so das,
wo es ein bisschen eltlich ist,
aber ansonsten steht diese Definition einfach wie ein Fels da und ist einfach sehr,
sehr gut,
um deutlich zu machen,
was wir
immer noch hier in Java
auch vorfinden
So, und jetzt kommen wir zu dem Punkt,
wo es spannend wird. Also das war bisher,
haben wir so gesehen, diese primitiven Typen in Float Double
Bulien und so weiter. Relativ einfache Datentypen. Jede Programmiersprache hat sowas,
so vordefinierte Typen, habe ich letztes Mal schon erzählt.
In Java sind es halt so irgendwie acht primitive Typen und dann vielleicht noch stringen.
Die sind so da und dann kommt noch eine ganze Menge dazu,
was man selbst schreiben kann. Das ist nicht immer so gewesen,
es gab durchaus Ansätze in der Welt der Programmiersprachen,
da haben wir gesagt, naja,
wir haben jetzt hier eine Sprache für kaufmännische Anwendungen,
Cobol,
da sind dann die Datentypen eben
genau für diesen Zweck
Eingebrannt in die Sprache oder PL1,
eine Vielfalt vordefinierter Datentypen, um möglichst viele Anwendungsfälle abzudecken.
Durchgesetzt hat sich eher das Konzept von Programmiersprachen,
in denen man eigene Typen definieren kann.
Das ist was, was ihr schon teilweise gemacht habt,
ohne dass es euch bewusst war.
Da gehen wir gleich mal so ein bisschen genauer drauf ein.
Das heißt, ihr könnt neue Datentypen bauen.
Das ist das universelle Konzept von eigentlich allen Programmiersprachen.
Also wenn ihr zum Beispiel mit komplexen Zahlen rechnen wollt,
dann könnt ihr euch in vielen Programmiersprachen einen eigenen Typ Datentyp komplexe Zahl definieren.
Dann könnt ihr mit diesen komplexen Zahlen rechnen und ähnliches machen
Okay. Ja, wenn wir das dann jetzt uns genauer ansehen wollen,
dann haben wir, wie gesagt, bisher gesagt,
die Klassen, die ihr definiert habt, das waren so,
hatte ich schon mal angedeutet, sind eher einfache Klassen.
Das heißt, die Zustände dieser Exemplare sind definiert über deprimitiven Typen.
Also beim Konto war das so,
da war nur so dieser Saldo als Feld enthalten,
bei der Ampel war es irgendwie drei Felder vom Tybulien,
die festgelegt haben, in wie vielen Zuständen denn so ein Exemplar sein kann.
Wie ist das denn hier, wenn ich jetzt so Exemplar
da klasse Ampel habe. Und die Klasse definiert drei Exemplar-Variablen
. Da hat ja jedes Exemplar drei Felder vom Typolien,
wie viele verschiedene Zustände kann denn so ein Exemplar überhaupt annehmen?
Rein technisch. Da sagt jemand acht, mit den Fingern,
die angedeutet, genau, acht verschiedene,
weil ich natürlich für jede Belegung, es gibt ja nur zwei Belegungen,
für jede Belegung habe ich dann wieder die anderen, alle Kombinationen.
Also habe ich hier acht mögliche Belegungen. Ihr wisst aber auch,
dass fachlich in dieser Ampel Implementation, die ihr gebaut habt,
nur vier davon gebraucht wurden.
Es gab nur vier Zustände, die da verwendet wurden bei
dieser Lösung mit den drei Bulls
Muss man auch mal drauf achten. Technisch ist das eine,
wie viele Zustände kann so ein Objekt haben?
Fachlich, wie viele davon sind sinnvoll für den Anwendungsbereich?
Gut, und bei der Waage war das mit dem Gewicht und so weiter.
Und das waren die einfachen Typen. Jetzt gucken wir uns an,
Klassen, die nicht nur ihre Felder über primitive Typen definieren,
sondern Klassen, die auf andere Klassen verweisen.
Das heißt, ein Objekt besteht nicht nur aus in seinen Feldern
irgendwie aus primitiven Typen, sondern kann wieder auf andere Objekte verweisen.
Und dann entstehen sogenannte Objektgeflechte
Das heißt, die Objekte können über Referenzen miteinander verbunden sein und das ist das,
was wir jetzt uns ansehen werden, das sind die sogenannten Referenztypen in Java.
Und ich habe schon ein paar Mal jetzt angedeutet,
Referenztypen sind irgendwie fies, die sind irgendwie komisch,
das wissen wir aus den letzten Jahren,
für viele Programmieranfänger ist das eine Hürde.
Also auch da wieder der Hinweis, ordentlich sich das reinziehen,
was wir jetzt hier so machen,
auch in den Übungen gut mitmachen,
weil wir das einfach dann fortlaufend immer wieder brauchen werden
Aber man kann das nicht relativ anschaulich verdeutlichen, was denn
der Referenz eigentlich ist. Ich habe hier so ein Bild,
was ich ganz schön finde,
das ist so ein Drachen da in der Ecke,
damit dich dieses Objekt am Himmel irgendwie kontrollieren kann,
brauche ich eine Schnur.
Ich muss also irgendwie das Ding irgendwie darauf zugreifen können.
Das könnt ihr euch so ein bisschen auch so vorstellen mit
so einer Referenz. Ihr habt die Referenz in der Hand,
aber das Objekt ist ganz woanders. Und ihr habt nur
irgendwie diese Referenz als eine Art Verbindung zu dem Objekt.
Und das ist tatsächlich so, dass hier die Klientenobjekte,
wenn sie ein Dienstleisterobjekt benutzen,
immer das über eine Referenz machen
Also auch wenn ihr ein neues Objekt erzeugt,
einen Konstrukteaufruf macht, dann kommt da tatsächlich letztendlich eine Referenz zurück.
Ich zeige das mal wieder an diesem Zeichnerprojekt. Der Zeichner hat ja hier,
ich muss das hier mal eben auffalten, hat ja hier,
benutzt er ja an seiner Implementation drei Klassenkreis, Quadrat am Dreieck.
Und hier ist es tatsächlich so, in diesem Quelltext,
den ihr schon ein paar Mal gesehen habt,
da steht hier ein Aufruf,
ein Konstrukteaufruf
Ja. Und dadurch, da kommt eine Referenz zurück und
das hier ist eine Referenzvariable. Und diese Referenz,
die da zurückkommt, die wird dann dieser Variablen zugewiesen.
Und dann kann ich über diese Variable und damit indirekt über
die Referenz, die darin gespeichert ist,
tatsächlich jetzt auf das Objekt zugreifen, was hier erzeugt wurde.
Also hier wurde irgendwo ein Objekt erzeugt und darauf kann man
jetzt zugreifen über diese Referenzvariable. Das ist eine Referenzvariable.
Das kann man sich mal dadurch verdeutlichen, dass das funktioniert,
habt ihr gesehen, ihr habt das schon oft genug gesehen.
Ich kann jetzt mal diesen Aufruf hier auskommentieren
Und dann wird tatsächlich hier nur die Variable verwendet,
aber ohne dass jetzt da eine Referenz auf ein Objekt zugewiesen wurde.
Das kann ich jetzt mal versuchen zu übersetzen. Da wird es
aber eine Fehlermeldung geben. Das kennt ihr möglicherweise auch schon.
Eine lokale variable Wand wird hier deklariert, aber nirgends initialisiert.
Und das lässt der Comparder nicht zu. Das heißt,
ich kann hier gar nicht den Aufruf machen.
Also schon statisch. Bei der Programmübersetzung sagt der Compirer,
nee, das geht so nicht, das könnte in die Hose gehen,
wenn du da irgendwas mit einem unitalisierten Objekt machen willst.
Deswegen machen wir es jetzt hier so,
dass ich das wieder einkommentiere und ich trickse jetzt den Compiler aus
Sage jetzt hier einfach mal null. Was null ist,
werde ich gleich noch erklären. Aber jetzt habe ich diese Referenzvariable,
über die ich ja diese Aufrufe immer mache und sage,
ich soll explizit auf kein Objekt verweisen.
Dann ist der Compiler jetzt zufrieden. Dann sagt er,
na gut, der Programmierer hat wohl gewusst,
was er will, obwohl er auch hier sehen könnte,
hier ist ein Nall und direkt danach wird über die Nallreferenzen Aufruf gemacht.
Könnte man als Compiler ein bisschen, vielleicht, das
kann man direkt erkennen. Es geht aber nicht immer,
wenn das als Parameter übergeben würde,
würde man ja schon nicht mehr wissen, was da übergeben wird.
So, das kann ich jetzt übersetzen.
Und jetzt kann ich das auch ausführen. Ich kann also
jetzt hier mal so einen Zeichner mehr erzeugen.
Und dann gebe ich hier irgendwie gelb als Parameter an.
Nicht gelb, gelb. So, und dann kracht das hier.
Java-Leng-Null-Pointer-Acception-Null. Das heißt, was tatsächlich passiert ist,
diese Referenzvariable zeigt auf kein Objekt, weil der Konstruktoraufruf,
den habe ich weggenommen und es kam keine Referenz zurück und
dann ist da einfach ein Aufruf ins Leere gegangen.
Das ist etwas, was ganz wichtig ist,
wenn ihr mit Referenzen arbeitet, die können null sein.
Also eine Referenzvariable kann durchaus irgendwie auf kein Objekt zeigen
Das gucken wir uns jetzt mal ein bisschen genauer an.
Die Variablen, die ihr bisher kennengelernt habt,
die lokalen Variablen, so primitive Typen und so weiter.
Sowas wie Int-Antwort. Ganz zentral immer wieder bei Variablen.
Die haben einen Typ und die haben einen Namen. Ein Name,
den du als Bezeichner hast, muss ein Typ angegeben werden.
Und man kann denen irgendwie einen Wert zuweisen. Das heißt, dieser Behälter,
den die Variable darstellt, da kann man was reinspeichern.
Also hier haben wir zum Beispiel jetzt mal 42 da reingelegt.
So, diese Referenzvaria, wie wir sie gerade gesehen haben,
wie diese Referenzvaria bewandt in diesem Quelltext,
die sieht eher so aus
Das heißt, wir haben wieder einen Speicherplatz, das ist hier das Grauangedeutete.
Das ist die eigentliche Variable. Und da drin liegt dann
eine Referenz, wenn dann tatsächlich eine gültige Referenz drin liegt.
Die kann ich in der Variablen speichern. Und diese Referenz
verweist auf das eigentliche Objekt, das ist ganz woanders.
Irgendwo im Speicher, wir wissen gar nicht genau wo.
Das ist eine Referenzvariable. Und das ist wirklich ganz fundamental
. In Java gibt es genau diese beiden Kategorien.
Das ist orthogonal zu den drei variablen Arten,
die wir letzte Woche kennengelernt haben.
Lokale Variablen,
formale Parameter und Exemplarvariablen
Das sind drei Variablenarten. Und Orthogonal,
dazu gibt es halt bei beiden Referenzvariablen und Wertvariable.
Einfach abhängig vom Typ. Eine Wertvariable ist es immer genau dann,
wenn es einer der primitiven Typen in Java ist.
Also die acht Basistypen, die ich letzte Woche vorbestellt habe.
Alle anderen Typen und wirklich alle anderen Typen sind Referenztypen.
Das heißt, auch die Variablen sehen so aus,
die halten eine Referenz auf ein Objekt. Das heißt,
wir haben eine zusätzliche Indirektion, das ist wie ein Verweis.
Und da ist es natürlich auch wieder so,
so eine Referenzvariable hat einen Typ,
das ist dann
ein Referenztyp
Und tatsächlich ist es so,
dass sie jede Klasse in Java, die findet einen Referenztyp.
Das heißt, wenn ich sowas habe wie mein Konto,
was ihr ja schon tausendmal bei uns jetzt gesehen habt,
dann könnt ihr eine Variable vom Typ Konto deklarieren.
Die Variable heißt ein Konto, hat den Typ Konto.
Okay, sehr schön. Das ist nicht gut. Dass man
eben hier mein, muss ich jetzt nicht, ich brauche kein Netz.
Gut. Habe also hier eine Variable vom Typ Konto und
was kann da drin gespeichert sein in so einer Variable?
Naja, nur eine Referenz. Es ist immer wirklich nur
eine Referenz da drin. Es ist nicht das ganze Objekt
da drin gespeichert
Nein, das Objekt ist immer irgendwo anders. Okay.
Dann ist es ziemlich wichtig, sich klarzumachen, dass Referenztypen,
Typen sind. Das heißt, ich habe den Typbegriff eingeführt,
ich habe gesagt, Typ, Wertemenge plus Operationen.
Das gilt genauso bei den Referenztypen jetzt hier.
Also wenn ich sowas habe wie den Typ Konto,
dann hat er als Wertemenge, kann ich sagen,
das sind einfach die Menge aller Exemplare, die ich von dieser Klasse erzeugen kann.
Habe ich 500 Konten erzeugt, ist die Wertemenge,
hat 500 Elemente groß.
Also beliebig viele Exemplare können erzeugt werden
Ist die Wettemenge auch eigentlich unbeschränkt. Das ist formal schwer zu greifen,
aber anschaulich ist es, glaube ich, relativ einfach.
Okay, und die Operation, die ein Referenztyp definiert,
sind genau die Methoden, die an den Exemplaren der Klassen aufgerufen werden können.
Also wirklich nur genau die. Wenn ich jetzt mir hier
das wieder angucke, was ich hier jetzt gemacht habe,
ich kann ja hier mal dieses, ja, das wieder einkommentieren.
Jetzt kann ich hier an dieser Stelle auch mal was aufrufen, wie wand.drehen.
Ja, sind taktisch vollkommen korrekt, ist ein Methodenaufruf,
also Level 1, Syntax würde sagen, ja, syntaktisch in Ordnung.
Der Typ, den Wand hat. Der Typ,
den Wand hat, ist ein Referenztyp, nämlich Quadrat.
Der Typ, Quadrat, definiert Operationen.
Naja, es sind genau die Methoden an der Schnittstelle.
Das sind genau die Operationen, die der Typ definiert.
Und da ist eine Methode drehen, nicht dabei.
Und da ist es wieder wunderbar, wenn ich jetzt glaube,
ich könnte jetzt irgendwie Wand drehen, aufrufen,
da sagt der Compiler, nee, gibt's nicht.
Cannot fine Simple, Methode drehen. Ja, gibt's nicht.
Auch da ist das eigentlich ganz gut, wenn ich glaube,
dass ich da eine Methode drehen finde und das hinschreibe,
dann sagt der Compiler,
gibt's nicht,
dann habe ich entweder einen Denkfehler gemacht oder ich habe irgendwo
vielleicht mich vertippt oder ähnliches
Okay. Das nehmen wir wieder weg hier. Das ist ja Unfug,
wir wollen ja keine Wände drehen. Das heißt also,
auch da wieder, das ist diese Analogie mit dem Typbegriff,
wir haben so primitive Typen, Wertemenge plus Operationen,
auch bei den Referenztypen, Wertemenge aller Exemplare, Operationen,
die Methoden, die ich da aufrufen kann als Klient.
Und dann hat man nämlich genau diesen Zusammenhang,
der sehr zentral ist, Schnittstelle und Typ,
die Schnittstelle einer Klasse, haben wir schon gelernt,
das sind die öffentlichen Methoden und die definieren die Schnittstelle
ihrer Exemplare
Außerdem wissen wir jetzt einen klasse definierten Typ, einen Referenztyp.
Das heißt, genau diese öffentlichen Methoden sind die Operationen des Typs.
Also ab sofort ist bei uns immer so dieser Begriff Operation
primär verbunden, wenn wir über Typen reden, ganz allgemein.
Und Methoden sind sehr konkret für unsere Klassen und unsere Referenztypen.
Ja, okay, dann gehen wir jetzt nochmal so
ein bisschen in so ein paar Details rein von Java.
Ich kann das mal zeigen. Also erstmal ist es so,
tatsächlich alle Objekte in Java werden über Referenzen verwendet.
Es geht nicht anders. Wenn ihr mit Objekten umgehen wollt
in Java, müsst ihr das mit Referenzen machen
Auch die Übergabe eines Objektes als Parameter erfolgt
immer nur als Übergabe des Wertes einer Referenz.
Das muss ich jetzt mal vielleicht ein bisschen konkreter machen.
Wir gehen mal hier in den Zeichner rein. Und ich
führe mal einen weiteren Parameter ein. Also hier Quadrat,
Kuh. Das ist ein weiterer formaler Parameter. Habt ihr
hoffentlich jetzt schon mehrfach gemacht, sowas. Das heißt,
als Klient bin ich jetzt aufgefordert, ein Quadrat zu übergeben.
Jetzt könnte ich hier einfach mal statt sagen,
statt New Quadrat mache ich hier einfach Kuh.
Übergebe hier Kuh
Das kann ich ja machen. So, das wird sich
jetzt übersetzen lassen, klar. Das heißt,
jetzt kann ich auch tatsächlich das aufrufen hier, mein Zeichner.
Und muss jetzt, wenn ich da Zeichen aufrufe, eine Farbe übergeben.
Und dann muss ich irgendwie noch ein Exemplar übergeben.
Jetzt ist die Frage, wo kriege ich jetzt ein Exemplar her?
Gut, das ist jetzt genau der Punkt, wo es interessant wird.
Ich kann mir ja von der Klassik Quadrat hier mal so
ein Exemplar erzeugen.
Dann habe ich hier tatsächlich Quadrat
Ach, meine Maus, die ist irgendwie so ein bisschen besoffen,
habe ich das Gefühl, die wackelt so dermaßen.
Jetzt, das hier, haben wir bisher immer gesagt,
so informell für euch, das sind die Objekte,
die da unten auf der Objektleiste liegen.
Wenn wir es jetzt ein bisschen genauer sagen wollen,
dann sagen wir, das sind eigentlich Referenzen.
Und noch genauer sind es eigentlich Referenzvariablen, weil die Dinger haben ja
auch einen Namen, die hier stehen. Das heißt,
ich kann jetzt, wenn ich diese Methode von dem Zeichner aufrufe,
hier, dann kann ich jetzt sagen,
ich übergebe als ersten Parameter eine Farbe und als zweiten Parameter
kann ich jetzt hier Ups, das war falsch,
im falschen Feld gewesen.
Ich möchte ja hier eine Farbe übergeben.
Hallo, hier eine Farbe, hallo, Farbe.
Und hier in diesem Feld, meine Güte, ist das zäh.
Boah. Nicht zu fassen. Jetzt Quadrat. Ich kriege mich
ja nicht auf. Ich tippe das jetzt einfach ein,
das geht viel leichter. Quadrat. Also eigentlich geht das ja
auch einfach durchklicken. Jetzt übergebe ich hier die Referenz.
Das heißt, ich übergebe jetzt eine Referenz auf dieses Objekt,
was ich schon erzeugt habe.
Also hier, da wird jetzt hier das aufgerufen.
Jetzt habe ich hier eine Referenz auf Ein Objekt,
das kann man sich ja so, habt ihr ja schon gesehen,
Objektinspektor, dann habe ich jetzt tatsächlich hier die Möglichkeit,
an diesem Objekt hier irgendwie unsichtbar machen aufzurufen.
Und dann wird tatsächlich in der Zeichnung dieses Quadratwasser verwendet,
wird auch unsichtbar gemacht. Das ist eine Referenz, die
ich jetzt hier einfach verwenden kann. Führt jetzt dazu,
dass es hier nach vorne kommt und so weiter, da sind so Randprobleme.
Aber ich kann tatsächlich über diese Referenz das Ding manipulieren.
Das heißt, ich habe nur die Referenz kopiert.
Ich habe nicht das Objekt da rein kopiert,
sondern ich habe diese Referenz übergeben. Das heißt,
sowohl diese Methode von Zeichner hat eine Referenz bekommen,
ich habe immer noch eine Referenz hier als Klient
und beide können wir jetzt da an diesem Objekt irgendwas manipulieren
Okay, das heißt also, Übergabe von Objekten immer nur als Übergabe von Referenzen.
Und bei der Zuweisung einer Referenz war ja,
und die Referenz kopiert, nicht das referenzierte Objekt.
Also auch diese Parameterübergabe, da wird nicht das Objekt kopiert,
sondern nur die Referenz.
Ganz wichtig. Der Gleichheitstest mit dem Operator gleich gleich,
auf Referenz war ja nun prüft die Gleichheit der Referenzen.
Also zeigen sie auf dasselbe Objekt. Das prüft nicht,
ob die referenzierten Objekte gleich sind. Klar,
es werden zwei Referenzen auf dasselbe Objekt zeigen,
denn das Objekt ist ja immer gleich zu sich selbst
Ich kann auch in Java Objekte vergleichen. Dafür gibt es aber eine Operation,
die lernen wir erst auf Level 3 oder 4 kennen.
Hier geht es momentan erst mal nur darum zu wissen,
wen ich zwei Referenzen vergleiche, mit gleich gleich,
dann prüfe ich damit, ob sie auf dasselbe Objekt verweisen.
Okay, Referenzvariable kann auch den besonderen Wert Null haben,
das haben wir schon auch schon gesehen.
Ich habe da eben Nall zugewiesen. Dann kann ich natürlich
auch keine Aufrufe machen. Also dann geht einfach
der Aufruf schlägt fehl. Das heißt, was da passiert
an dieser Stelle in dem Zeichner nochmal
Kann man sich wirklich so vorstellen, bei diesem Aufruf 4
, Wandfarbe ändern. Da wird eigentlich in das,
ob die variable Wand reingeguckt ist, eine Referenz.
Und diese Referenz wird nachverfolgt bis zum Objekt. Und dann
wird im Objekt die Methode aufgerufen, nämlich Farbe ändern.
Okay, und wie gesagt, man kann Referenzen auch auf Gleichheit miteinander vergleichen.
Ich kann also zum Beispiel jetzt hier schreiben, Quadrat,
Q2, ist gleich Quadrat 1. Quadrat
1. Jetzt habe ich eine neue Variable Q2 deklariert hier
und initialisiere sie mit der Referenz Quadrat
Und dann kann ich tatsächlich jetzt hier Q2 mir auch anzeigen lassen.
Und ich kann sogar die Referenz jetzt hier mir rüberziehen.
Jetzt habe ich hier tatsächlich, da sieht man es tatsächlich,
dass es ein Unterschied ist,
ob man über die Objekte redet oder über die Referenzen.
Ich habe jetzt zwei Referenzen auf dasselbe Objekt. Das heißt,
wenn ich jetzt hier einen Doppelklick mache und mir einen Objektinspektor
anzeigen lasse, dann ist das der hier.
Jetzt mache ich das Gleiche mit dem hier.
Doppelklick, jetzt kommt der gleiche Objektinspektor.
Es ist das gleiche Objekt, es ist sogar dasselbe Objekt.
Also tatsächlich beide Referenzen zeigen auf dasselbe Objekt. Und ich
kann tatsächlich jetzt auch über beide Referenzen dieses Objekt verändern.
Ich kann es also jetzt hier irgendwie unsichtbar machen.
Da sieht man, das hat sich da oben geändert auf Falls.
Und über diese kann ich es aber auch wieder sichtbar machen.
Da kann ich jetzt einfach sagen, hier sichtbar machen.
Und dann ist es wieder sichtbar. Das geht also
über zwei verschiedene Referenzen. So, dieses Konzept,
dass man irgendwie sozusagen über so eine Indirektion auf Dinge zugreift.
Das heißt in anderen Sprachen auch, Pointer,
da gibt es eine ganze Menge Zeug dazu.
In Java ist das Schöne, die Dinge sind ziemlich sicher.
Ihr müsst so eine Referenz haben, sonst könnt ihr
gar nicht mit dem Objekt irgendwas machen.
Wenn ihr so ein Ding aber habt,
könnt ihr es beliebig durch die Gegend kopieren,
ihr könnt das aber nicht verändern.
Ihr könnt also nicht sowas machen wie,
in manchen Sprachen gibt es sowas wie Pointer-Arrithmetik. Das heißt,
Ich weiß sozusagen,
dass diese Referenz irgendwo in den Speicher zeigt und ich addiere
einfach jetzt hier auf diese Referenz ein bisschen was drauf,
dann zeigt die Referenz ein bisschen tiefer in den Speicher und dann zeige ich auf ein anderes Objekt.
Das ist so, wie das in manchen Sprachen funktioniert und das geht in Java gar nicht.
Und das ist tatsächlich, dient sehr der Sicherheit. Gut,
wenn wir jetzt aber so Referenzen so,
wenn die so wahnsinnig wichtig sind,
wenn wir ohne Referenzen gar nichts machen können,
dann müssen wir natürlich uns überlegen, wie kommen wir an die Dinger denn ran?
Und da gibt es prinzipiell erstmal zwei Möglichkeiten. Die eine ist,
Erzeuge mir mein Objekt selbst, das ich benutzen will.
Das ist tatsächlich hier so gemacht, ja,
also hier in Zeichner, der macht sich seine ganzen Objekte,
die er verwenden will, erzeugt er sich selber.
Er ruft also hier auf New Quadrat, New Quadrat,
New Quadrat und New Dreieck und so weiter.
Also die Objekte, die er manipulieren will, erzeugt er sich selber.
Das ist die eine große Möglichkeit. Die andere ist,
und deswegen steht das hier so ein bisschen innerhalb einer Methode.
Also alles, was in einem Java-Programm passiert, passiert in Methoden.
Es gibt keine andere Möglichkeit, irgendwo Anweisungen hinzuschreiben.
Vielleicht noch in den Konstruktoren und so,
aber so im Großen und Ganzen kann man eigentlich sagen,
die ganze Action passiert in den Methoden
Ja, also in den Rümpfen von Methoden. Und das heißt,
man muss sich einfach überlegen,
wenn ich in einer Methode auf andere Objekte zugreifen will,
dann habe ich entweder die Möglichkeit,
mir die Dinger selbst zu erzeugen, wie der Zeichner das macht.
Oder ich lasse ihn mir geben, die Referenzen.
Also zum Beispiel hier zweite Möglichkeit, er hält die Referenz
auf den Dienstleister, unmittelbar als Parameter der Methode.
Haben wir gerade gesehen, wir konnten ja da auch eine Referenz
offen zu benutzen, das Objekt reinreichen als formalen Parameter.
Dritte Möglichkeit ist tatsächlich, dass diese Referenz in den Exemplarvariablen
gespeichert ist. Und wir wissen ja, beim Objekt kann
alle Methoden auf die Exemplarvariablen zugreifen
Und die nächste Möglichkeit ist natürlich auch noch,
ich habe schon eine Referenz auf ein Objekt und das liefert mir dann,
wenn ich jetzt auch, wofür noch weitere Referenzen wieder.
Das werden wir uns alles noch ausführlicher an den ganzen nächsten Wochen ansehen.
Aber letztendlich immer die Idee, ich brauche diese Referenz, um überhaupt irgendwas machen zu können.
Wenn man sich das erst mal so dann veranschaulicht hat und das verstanden hat,
dann ist es einfach so, eigentlich kann man sich jedes Java-Objekt,
jedes Java-System so vorstellen, wenn es denn läuft,
das sind lauter Objekte, die da so rumschwirren,
hier so angedeutet durch die Synitten, ovalen Dinge,
das sind alles Exemplare oder Objekte und die haben in ihren Zuständen,
haben die entweder primitive Typen,
Also primitive Werte gehalten.
Oder sie halten Referenzen. Also hier kann zum Beispiel
ein Referenzgespräch sein, auf dieses Objekt hier.
Und dieses Objekt wiederum kann Referenz halten, die aber vielleicht
gerade ein Nall ist. Das soll hier andeuten,
zeigt auf kein Objekt, ist ein Nall, zeigt ins Leere.
Oder wie bei der Zeichnermethode hier, da ist es ja so,
dass diese Referenz nur innerhalb der Methode lebt.
Die Objekte leben nur so lange, solange die Methode ausgeführt wird.
Wenn die Methode zu Ende ist, ist es wieder vorbei.
Das heißt also, diese Referenzen können hier überall auftreten.
Und es kommt zu so einem Objektgeflecht.
Und das kann man sich wirklich so vorstellen,
Objekte in Java interagieren, arbeiten zusammen,
indem sie sich gegenseitig über Referenzen benutzen
Das ist alles, was ihr über Japan wissen müsst.
Wenn ihr das verstanden habt, dann habt ihr schon ziemlich viel verstanden.
Wenn man das jetzt hat, was wir gerade gesehen haben,
ich hatte zwei Referenzen auf dasselbe Objekt und ich konnte über beide Referenzen das Objekt verändern.
Dann kommen wir zum sogenannten Alias-Problem. Das ist gerne als Problem bezeichnet,
weil man dadurch dann Effekte hat,
dass wenn der eine etwas ändert,
der andere das aber gar nicht verursacht hat,
dann hat sich sozusagen unter der Haube, hat sich was geändert,
der das gar nicht verursacht hat,
wundert sich,
dass sich der Zustand des Dienstleisters
plötzlich geändert hat
Das nennt man auch Seiteneffekt. Ja, also hier tritt
was auf und jemand anders kriegt es am Rande mit.
Das ist nicht schön in vielen Situationen, aber auch nicht wirklich unbedingt ein Problem.
Also dieses alias Ding habe ich gerade eben schon gezeigt in Blue Jay.
Ist das jetzt wirklich ein Problem oder ist es eine Chance?
Und da kann man jetzt sagen, ihr könnt mit,
ihr könnt euch vorstellen, so Objektgeflechte,
wenn ihr den Begriff schon hört, ein Geflecht,
da kann man sich beliebig komplexe Strukturen bauen.
Und wenn man irgendwie fortgeschrittener Java-Programmierer ist, wird man auch auf solche Systeme stoßen,
wo einfach kreuz und quer die Referenzen gespannt sind.
Und das ist dann wirklich ziemlich fürchterlich eher wie ein Wollknäuel
und dann wird es auch sehr schnell unübersichtlich.
Dann ist die Software nicht mehr wartbar, da gibt es dann eben Überlegungen,
wie man das dann von der Struktur besser machen kann.
Die Chance ist aber da wirklich das beliebig komplex zu machen.
Das ist zugegebenermaßen so, aber man kann eben halt auch,
wenn man das sinnvoller und vernünftig einsetzt,
kann man damit sehr mächtige Strukturen bauen.
Also ihr seht ja, was heutzutage so an Software existiert,
das ist sehr häufig mit imperativen Programmiersprachen entwickelt.
Das heißt, wir müssen erstens Referenzen sehr gut verstehen,
um sie dann vernünftig anwenden zu können und wir müssen dann auch irgendwann diszipliniert damit umgehen,
lernen, damit wir eben halt auch Software schreiben,
die wartbar bleibt
Und das ist nicht so ganz einfach. Okay,
da sind wir mit der ersten Hälfte auch schon ziemlich weit, also nochmal zusammengefasst.
Java unterscheidet diese beiden Typfamilien. Es gibt Werttypen und Referenztypen.
Die Werttypen sind genau acht, es gibt acht in Java.
Nicht mehr, nicht weniger genau acht.
Letzte Woche war es dran, könnt ihr euch nochmal angucken.
Und dann gibt es Referenztypen. Alle anderen Typen in Java
sind Referenztypen. Alle. Sowohl die Vordefinierten als auch die,
die ihr selbst dazu definiert. Wer Typen fest definiert,
beliebig neue Referenztypen, definierbar, Referenztypen benutzt man und Referenzen,
um Objektgeflechte zu bauen, sind in sehr unterschiedlich realisiert.
Also in Java heißen die jetzt Referenzen,
dieses Konzept von solchen Verbindungen zu irgendwelchen anderen Objekten im Speicher.
Zeiger Arathmetik und sowas gibt es in C und C Plus
, wollen wir hier nicht weiter ansehen.
Denn da würden Programme wirklich schwer wartbar und beherrschbar,
wenn man das zu exzessiv benutzt.
Java ist in der Hinsicht ziemlich sicher,
die Referenzen können nicht manipuliert und verändert werden.
Und Java ist aus dem ziemlich einfach,
jede Paradeübergabe habe ich irgendwie auch, glaube ich,
schon mal gesagt, in Java erfolgt per Wert.
Das heißt, es werden immer Dinge kopiert. Das heißt,
wenn ich ein Objekt an eine Methode übergebe,
dann übergebe ich eigentlich nicht das Objekt.
Ich kopiere nicht das Objekt, sondern ich kopiere nur die Referenz,
die ich habe. Dann hat die aufgerufene Methode auch eine
Kopie dieser Referenz und kann auch auf dieses Objekt zugreifen.
Aber es werden keine Objekte dabei kopiert. Objekte kann man,
wenn man sie kopieren will, natürlich auch explizit kopieren.
Ja, das ist schon alles, was ich jetzt zu
Referenzen sagen wollte. Gibt es Fragen zu diesem Thema Referenzen
? Das ist möglicherweise eine ziemlich harte Nummer.
Ihr seht jetzt nicht so glücklich aus. Ich werde in
den Übungen da sicherlich noch das ein oder andere
Mal damit umgehen
Wir werden das ein bisschen noch üben. Keine Sorge.
Da ist eine Frage. So sagten Sie, dass die,
dass die alles noch einzeln auf das Objekt werden.
Okay, er sagt, er fragt,
ich hätte gesagt, dass es nur Referenzen sind,
mit denen man umgehen kann und nicht das Objekt selbst.
Und er fragt, wo liegt denn das Objekt selbst?
Das ist eine sehr gute Frage. Die Antwort jetzt ist,
dass es uns noch egal. Die etwas vollständigere Antwort ist,
wird auch in den nächsten Wochen noch beantwortet,
sie liegen auf dem Hieb auf einen Stapel,
aber nee, nicht auf Anschau, auf einem Haufen,
auf einem Haufen von Speicher.
Es gibt also irgendwo Speicher, der es reserviert für neue Objekte.
Und da werden immer so Stücke rausgeschnitten,
um dann irgendwie die zu reservieren für Objekte.
Das ist aber ein technisches Detail von Lara. Erstmal müsst
ihr nur einfach verstehen, wenn ihr ein Objekt erzeugt,
dann hat es Speicher. Und erst wenn ihr das Objekt
nicht mehr benutzt, wird dieser Speicherplatz wieder freigegeben.
Sonst noch Fragen, da oben ist noch eine Frage.
Es vergleichen die iPhones im Gewicht dort,
der Jahre wieder
auf ist
Amen. Ich hoffe, ich habe das richtig verstanden.
iPhoto, richtig? iPhoto. Also er spricht über eine Software und fragt,
ob es da nicht sehr ähnlich ist,
dass man eigentlich, wenn man so seine Fotos verwaltet,
dass man dann die Fotos als Originale irgendwo liegen hat und eigentlich in der Software,
die sie verwaltet und dann nach verschiedenen Kriterien sortiert und verschiedene Listen hat,
dass man da eigentlich auch nur Referenzen hat auf die Originale.
Das ist ähnlich. Ja, das ist tatsächlich so.
Also es werden da, aber es gibt in solchen Verwaltungstools
auch immer die Möglichkeit,
wieder Bilder zu kopieren
Ja, aber häufig ist es so,
dass man tatsächlich verschiedene Repräsentationen hat in verschiedenen Listen,
um dasselbe Foto in verschiedenen Kontexten zu sortieren.
Das ist vom Konzept recht ähnlich. Ja, es ist
richtig. Sonst noch Fragen, Hinweise zu Referenzen.
Da ist noch was. Ich weiß nicht, was das ist.
Okay, sie fragt nach dem Unterschied zwischen wertvariablen und Referenzvariablen.
Das ist einfach Ganz einfach, in Java ist es so,
es ist eine Wertvariable, wenn es ein Int,
ein Float, ein Double, ein Bite,
also diese primitiven Typen, das sind die Werttypen in Java.
In einer Variable mit einem Werttyp deklariert ist,
dann ist sie auch eine Wertvariable.
Und alle anderen sind Referenzvariable in Java. Also es ist
eigentlich ganz einfach, es ist nur erstmal komisch möglicherweise.
Sonst noch Fragen zu Referenzen. Da ist noch
eine Frage
Er fragt nach dem Typ String, den haben wir bisher so informell benutzt.
Ich werde in der nächsten Woche ausführlich auf Strings eingehen.
String ist auch ein Referenztyp. Genau. In Java
ist es genauso, dass auch die Strings Referenzvariablen definieren.
Gut, sonst noch Fragen. Keine weiteren Fragen. Dann
machen wir, oder da braucht noch eine Frage, nein.
Gut, dann machen wir jetzt fünf Minuten Pause.
Also, dann wieder ein bisschen Ruhe bitte.
Es geht weiter mit dem zweiten Teil. Ich werde ja
dieses Thema mit den Referenzen nochmal so ein bisschen aufgreifen gleich.
Also da kommen wir drauf. Jetzt gucken wir uns mal
die sogenannte UML an, die Unified Modeling Language.
Das machen wir deshalb, weil sie eine Standardnotation ist,
heutzutage für Objektsysteme. Also damit kann ich Objektsysteme gut visualisieren.
Und wir sehen uns insbesondere an, Klassendiagramme und Objektdiagramme
nicht viel mehr. Das ist das, was ihr braucht,
um in SE1 die UML wirklich nutzbringend einsetzen zu können.
Ich hole ein bisschen aus, um so ein bisschen zu verdeutlichen,
was da so alles dahinter steckt mit diesem Begriff Objektorientierung.
Die Objektnatur ist relativ alt, circa 1967 war der Anfang
der Objektorientierten Programmierung. Das war die Premiersprache, oh,
ich habe wieder den Freeze an, Entschuldigung.
Also hier, es geht um die UML,
wesentliche Diagrammtypen, Klassendiagramme und Objektdiagramme.
So, und diese Objektorientierten, vielen Dank für den Hinweis,
objektorientierten Aktivitäten
Objekte eine Programmierung, wie gesagt, das ist das Älteste.
In den 60er Jahren ist Simula entwickelt worden.
Dann kam Anfang der 70er Jahre Smalltalk dazu.
Das waren so die ersten Objekte internierten Programmiersprachen.
Da ist schon eine relativ lange Tradition in der Informatik.
Dann kommt als nächstes, das ist so ein bisschen eigentlich,
wie programmieren wir mit einer objektantierten Sprache?
Dann gibt es den Objekt notierten Entwurf. Das ist immer dann,
wenn man anfängt, größere Systeme zu bauen,
dann merkt man irgendwann, ich muss mir irgendwie was überlegen,
wie ich das besser strukturieren kann.
Da, wenn dann so Entwurfsentscheidungen getroffen innerhalb der Programmstruktur
Wenn ich für einen bestimmten Anwendungsbereich anfänge, anfange eine Software zu entwickeln,
dann betreibe ich oft Objekte und hätte Modellierung.
Das heißt, ich überlege mir,
wie ich bestimmte Elemente aus dem Anwendungsbereich in meiner Software abbilde.
Dann habe ich sowas wie ein Konto als Typ und als Klasse
in meinem System und so etwas wie eine Kontonummer und sowas wie einen Betrag und so weiter.
Das ist dann der Bereich objektensierte Modellierung. Dann,
um überhaupt in einem bestimmten Anwendungsbereich festzustellen, welche Probleme will ich denn lösen?
Gehe ich oft so vor, dass ich dann auch objektorientiert analysiere?
Also wie machen wir das? Wie komme ich in einem Anwendungsbereich dazu,
dass ich die Begriffe, die zentralen Begriffe kenne,
dass ich sie erfasse, dass ich sie in Beziehungen zueinandersetzen kann,
dass ich einfach eine gewisse Expertise in dem Anwendungsbereich entwickle,
um dann auch kompetenter Probleme lösen zu können.
Das sind alles so Geschichten, die es da, die
mein Objekt orientiert machen kann. Man kann es auch anders machen,
aber die Objektintierung ist da, sagen wir,
recht erfolgreich, die letzten 30, 40 Jahre.
Und dann gibt es Objekte, diese Vorgehensmodelle. Also diese Frage,
wenn ich jetzt in einem Projekt mit mehreren Leuten an einem
großen Softwaresystem arbeite, wie gehe ich denn da vor?
Mache ich das irgendwie wasserfallartig? Ich finde am Anfang irgendwie eine Anforderungsspezifikation,
dann mache ich einen Entwurf zwei Monate,
dann zwei Monate implementiere ich das und dann irgendwie zwei Monate teste ich das und dann liefere ich das aus.
Fertig, Software fertig. Wie ein Hausbau. Oder geht
man vielleicht ein bisschen anders vor, den man irgendwie immer
kleine Inkremente baut und mal wieder das Feedback sich vom Kunden einholt, agile Vorgehensmodelle.
Das sind so Sachen, die sind so erst in den 90er Jahren
dann intensiver diskutiert worden. Und dann Objekt- und Tiertometermodelle,
das ist dann diese Frage, wenn ich objektorientiert vorgehe,
was gibt es denn da so als Beschreibungselemente für Objektsysteme?
Also Klassenmetaklassen und ähnliches. Das sind so sehr abstrakte Themen. So,
und wir sind aber noch hier mehr oder weniger auf Ebene
Also wir machen Objekte der Programmierung, auch ein bisschen Entwurf,
praktisch keine Modellierung, das machen wir erst in der SE2. Die UML ist tatsächlich entstanden aus dieser Tradition von so viel Diskussion über diese verschiedenen Dinge,
insbesondere gab es einfach eine Zeit in den 90ern,
in der es verschiedene Päpste gab, in der Informatik-Community,
die bestimmte Notationen entwickelt hatten, wie man denn,
wenn man im Team arbeiten will, auch irgendwie an einem Whiteboard,
an einem Flipboard oder was weiß ich,
mal eben so ein paar Kästchen malt und dann sagt,
ah ja, hier, das ist die Klasse,
das ist die Klasse und dann sind die verbunden miteinander und dann Welche Bedeutung hat denn jetzt der Pfeil?
Das war an verschiedenen Notationssprachen sehr unterschiedlich. Es gab also
da unter anderem drei große Protagonisten in dem Bereich.
Die wurden auch dann die drei Amigos genannt.
Und die haben sich dann irgendwann in den 90er Jahren geeinigt,
wir diesen Turmbau zu Babel wollen wir nicht.
Wir wollen nicht verschiedene konkurrierende Notationen haben für Objektsysteme.
Wir führen das zusammen. Und es kam tatsächlich dazu,
dass dann die Unified Modeling Language von diesen drei Protagonisten führend definiert wurde.
Und die ist inzwischen schon ziemlich alt. Es gibt inzwischen
eine Version 2-1-2. Ursprünglich mal von Rational entwickelt,
aber inzwischen von der Object Management Group weltweit einem Konsortium betreut.
Das ist ganz schön, weil wir jetzt tatsächlich eine Notation haben,
die, ja, da gibt es wenig Diskussionen.
Also wenn man da ein Kästchen hinmalt, dann ist irgendwie klar,
was das Kästchen wohl bedeutet. Wenn man ein Pfeil malt,
der irgendwie durchgezogen ist, dann weiß man,
das ist was anderes, als wenn der Fall nur gestrichelt ist.
Das sind so Sachen, die sind einfach jetzt für UML definiert.
Das heißt, die Sprache ist nützlich zu lernen.
Ihr werdet, wenn ihr später irgendwo in Softwareprojekten arbeitet und
da auch objektorientiert entwickelt, ziemlich schnell sowas brauchen wie die UML
Auf verschiedenen Ebenen, und das ist jetzt die nächste Frage,
wofür braucht man die UML? Die Leute selbst,
die die Sprache in die Welt gesetzt haben, die sagen,
the UML is a language for visualizing, specifying, constructing und documenting.
Das ist, kann man so sehen, ja,
aber man muss es nicht so sehen. Tatsächlich ist es so,
und das ist jetzt, das sage ich an dieser Stelle immer ganz gerne,
hier kommt jetzt unsere persönliche Meinung rein, also die UML ist da,
sie ist wohl definiert, man kann damit tolle Sachen machen,
man kann vielleicht sogar damit auch Software konstruieren oder spezifizieren,
Gut.
Was wir sagen ist, hier unsere Gruppe an der Uni,
hat es Zürchhofen, Softwaretechnik und ich und auch noch die Kollegen,
UML ist super geeignet, um Software zu visualisieren.
Also ich kann tatsächlich, wenn ich jetzt ein System habe mit fünf Klassen,
dann kann ich fünf Klassen Kästchen dahin machen, die mit Pfeilen verbinden.
Damit habe ich sofort einen Blick darauf, wie es aussieht.
Das ist ja auch das Schöne an Blue Jay. Ich habe hier,
ja, also wenn ich jetzt hier tatsächlich mal alles ausklappe,
dann sehe ich hier tatsächlich jetzt irgendwie fünf Klassen und ich weiß genau,
aha,
der Zeichner verwendet anscheinend Kreis,
Quadrat und Dreieck und diese Klassen
wiederum verwenden irgendwie
die Leinwand
Auf einen Blick sehe ich so relativ viel Zusammenhang zwischen diesen Elementen.
Das ist gut. Ich kann also tatsächlich Software gut visualisieren mit
so einem Klassendiagramm. Ich kann auch sehr gut dokumentieren.
Ich kann tatsächlich einfach mir aus einem Software-System, so UML-Diagramme erzeugen lassen,
um dann irgendwie vielleicht auch eine Dokumentation zu haben,
welche Methoden da angeboten sind, vielleicht auch über Zeitläufe dann zu sehen,
wie neue Methoden dazugekommen sind und ähnliches.
Also das ist prima, dafür kann man die UML gut verwenden.
Es gibt aber auch Leute, die sagen,
wir wollen die UML benutzen, um damit zu spezifizieren.
Das heißt, spezifizieren, zu definieren,
was gebaut werden soll
Also bei visualisieren und dokumentieren, da ist es so,
die Software ist da und die UML ist ein Nachgedanke oder
vielleicht auch vorher, aber es gibt irgendwie zweitrangig.
Viele wollen jetzt die UML nach vorne schieben und sagen,
nein, wir wollen jetzt in der UML definieren, was gebaut werden soll.
Ich male also so ein paar Kästchen hin,
dann drücke ich auf den Knopf und schon kommen so ein paar Klassengerüste dabei raus,
die dann schon irgendwie ihre Verbindung miteinander haben.
Und ich muss nur noch den Code reinschalten. Oder tatsächlich
die Bestrebung, die UML zu einer echten Programmiersprache zu machen.
Es gibt Leute, die wollen UML zu einer Programmiersprache machen.
Das ist sie nicht gedacht. Die UML war als Modellierungssprache
gedacht. Das heißt, man wollte eine Notation haben,
um über Objektsysteme diskutieren zu können
Modulieren zu können. Modellieren ist etwas sehr Kreatives und meistens
. Und programmieren ist etwas, wenn man so will,
sehr, sehr hartes, sehr scharf definiertes.
Die UML ist nicht so scharf definiert in ihrer Semantik.
Programmiersprachen wie Java sind relativ scharf definiert. Also wenn ich
ein Programm hinschreibe, dann kann jeder sagen, naja,
dieses Programm macht das und das.
Wenn ich die Sprache gut kennt, weiß das dann.
Bei UML ist das, ist da sehr viel mehr Luft.
Und deswegen diese Versuche, die UML zu einer Programmiersprache zu machen,
halten, ich für Quatsch, meine persönliche Meinung,
das muss nicht die richtige Meinung sein.
Es gibt auch Leute, die wollen die UML benutzen,
um damit Software zu zu entwickeln.
Also tatsächlich irgendwie, ich modelliere etwas in UML,
baue sozusagen Modelle und dann später füge ich nur noch den Quelltext an den entsprechenden Stellen ein.
Das ist dann Model-Driven, Model-Driven-Architecture, so wird es auch genannt.
Ich halte es für relativ unrealistisch, aber es gibt Leute,
es gibt tatsächlich Menschen auf dieser Welt, die das betreiben.
Gut, das ist erstmal jetzt die Einordnung. Wir gucken uns
jetzt mal so an, was es für Diagrammarten gibt.
Es gibt eine ganze Menge. Es sind also einfach
grafische Notationen, irgendwelche Kästchen, irgendwelche Linien,
die zwischen diesen Kästchen gezogen werden können
Gibt es eben halt Klassendiagramme, Objektdiagramme, Komponentendiagramme,
Deployment, Diagramme, Paketdiagramme und so weiter.
Das sind so um Strukturen von Software-Systemen zu beschreiben.
Und dann gibt es so auch Diagrammarten,
um das dynamische Verhalten zu beschreiben, also was wie Aktivitätsdiagramme,
Use-Case-Diagramme, Sequenzdiagramme, das sind tatsächlich relativ mächtige Diagrammarten.
Jedes Diagramm hat irgendwie, ich weiß nicht, zig Modellelemente,
die dann irgendwie mit verschiedenen Verbindungen versehen werden können und so weiter.
Also es ist wirklich eine Riesensprache, muss man dazu sagen.
Also sie ist nicht klein und leicht, sondern groß.
Und Wir machen jetzt sozusagen den ersten Zugang über das,
was uns am ehesten nützt, nämlich Klassendiagramme und Objektdiagramme.
Das ist unser Fokus in SE1 und die gucken wir uns jetzt mal an.
Da würde ich sagen, juhu, lasst uns einkaufen gehen.
Jetzt gucken wir mal, was wir so haben.
Als erstes gucken wir auf Objektdiagramme. Und wohlgemerkt,
ich rede jetzt nicht über Klassendiagramme, sondern über Objektdiagramme.
Also ich versuche, deutlich zu machen,
wie man in der UML Objekte visualisieren kann.
Eine Möglichkeit ist das, wie es hier angedeutet ist.
Man sieht hier ein Kästchen und das ist ein Objekt.
Also ein Objekt, ein Kästchen. Dann gibt es hier
so verschiedene Elemente
Also oft ist es bei den Objektdiagrammen so, dass sie
so zwei Trennlinien haben. Da steht oben in dem oberen Drittel
dann oder in dem oberen Bereich der Objektbezeichner und der Klassenname.
Das ist immer so, der Name steht vorne,
da kommt ein Doppelpunkt und dann kommt der Typ oder die Klasse.
Also genau andersrum als wie in Java.
Und das ist unterstrichen. Das ist halt so in UML.
Die Dinger werden halt da unterstrichen. Gut, dann hier
, das sind das, was wir kennen als Felder.
Das sind die Felder eines Objektes. Die heißen in
der UML Attribute. Jetzt kann man darum streiten,
ob das ein guter Begriff ist,
Ich bin da eher nicht so glücklich mit. Aber in
der UML sollte man wissen, dass die Dinger halt Attribute genannt werden.
Die haben also auch wieder Namen und ein Typ.
Und man kann auch tatsächlich Belegungen schon angeben.
Also man kann sagen, hier ist Beleg mit dem Wert 200.
Also durchaus bei einem Objekt kann ich ja bei einem konkreten Objekt,
kann ich ja sagen, das ist mit diesen Werten belegt.
Und dann gibt es die Methoden. Und das ist dann
zum Glück anhaltlich. Die sprechen auch in der UML von Methoden
. Das sind also die Methoden Namen hier,
die dann auch angedeutet sind mit so Klammern.
Und man kann eben halt da auch Parameter angeben.
Man kann auch einen Ergebnistyp angeben. Das ist alles möglich
So, das ist tatsächlich so und das ist erst mal
sozusagen der formale Rahmen für so Objektdiagramm.
Jetzt gibt es da ganz viele Möglichkeiten, dieses Diagramm auch zu vereinfachen.
Also die UML ist extrem flexibel. Das ist auf der einen Seite gut,
auf der anderen Seite eben halt auch extrem schwierig,
dann die Semantik irgendwie noch scharf zu kriegen.
Deswegen, ich halte das sowieso für Quatsch,
die Semantik scharf kriegen zu wollen.
Aber okay, hier ist es tatsächlich so,
der Objektbezeichner kann weggelassen werden.
Ich kann auch
den Klassennamen weglassen
Fehlt der Objektbezeichner,
muss aber auf alle Fälle einen Doppelpunkt vor dem Klassennamen stehen,
damit man, wenn ich nur den Objektnamen reinschreibe,
ist ja kein Doppelpunkt, wenn ich nur den Typnamen angebe,
dann sollte da ein Doppelpunkt davor stehen,
um zu sagen, das ist eben halt der Typ.
Felder heißen Attribute, da kann der Typ oder auch der konkrete Wert weggelassen werden.
Ich kann also fast alles irgendwie weglassen. Ich kann auch komplett
die Dinger weglassen, die Felder in so einem Diagramm.
Und die Methodennamen können auch weggelassen werden.
Das heißt also so, in so einem Objektjahr muss nicht
viel drinstehen
Ein ganz entscheidender Punkt ist,
den wir auch über die ganzen Jahre jetzt immer deutlicher bemerkt haben,
ist, dass es ein großes Problem gibt,
wenn man die UML im Zusammenhang mit Java vermittelt.
In der UML gibt es die Möglichkeit, diese Objekte zu benennen.
Also ein Objekt in so einem Objektdiagramm kann einen Namen haben.
In Java ist ganz klar es so, dass die Objekte keinen Namen haben.
Die haben einfach keinen Namen. Wenn ich jetzt hier nochmal
dieses Beispiel hernehme, dass ihr eben schon gesehen habt,
ich habe hier zwei Referenzen gehabt.
Quadrat 1 und Quadrat
Ja, wenn ich jetzt auf eines doppelt klicke,
dann erscheint ja der Objektinspektor.
Ja, also jetzt hier, Objektinspektorin, sieht man hier Quadrat
1. Da steht jetzt tatsächlich, das ist ein Objektdiagramm,
also der Objektinspektor ist so eine Art vereinfachtes Objektdiagramm in gewisser Weise.
Und da steht eben halt hier drin tatsächlich Quadrat vom Typ Quadrat
1. Quatsch, Quadrat 1 vom Typ Quadrat.
Das Blöde ist, warum steht jetzt in dem Objekt
der Name der Variablen? Hier habe ich jetzt Quadrat 2,
wenn ich jetzt einen Doppelklick mache,
warum steht da jetzt nicht Quadrat 2
Weil weder Quadrat 1 noch Quadrat 2 richtig ist.
Das Objekt hat einfach gar keinen Namen.
Sondern die Referenzen, die haben ja einen Namen in Java.
Die Referenz Variablen, in denen die Referenzen gehalten werden.
Die haben einen Namen. Diese Objekte selbst, die sind
sozusagen anonym. Und das ist in Java wirklich gefährlich.
Also wenn man in Java deinen Namen ranschreibt,
dann neigt man dazu, zu verwechseln,
was ist das Objekt und was ist die Objektreferenz und was ist die Referenz Variable.
Also das ist etwas, wo man ein bisschen aufpassen muss.
Was wir pragmatisch machen, einfach,
das ist ja auch in Blue Jay so gemacht,
man sieht das hier,
die sind ja so ein bisschen abgerundet dargestellt,
auch hier,
Objekte sind so ein bisschen abgerundet in den Ecken
Das ist auch das, was wir machen hier in der Notation.
Also wenn ihr auch in den Übungen jetzt mal ein Objektdiagramm
zeichnen sollt, dann bitte malt so leicht abgerundete Rechtecke.
Dann lassen wir den Namen immer weg. Also in Java ist es einfach so,
es ist nicht sinnvoll, da einen Namen reinzuschreiben.
Deswegen lassen wir es weg. Ein Objekt hat keinen Namen,
aber immer einen Typ. Ein Exemplar ist immer Exemplar einer
Klasse und bleibt das auch für den Rest seines Lebens.
So, also das kann man dann so hinschreiben, also unterstrichen.
Dann nennen wir die Dinger halt Felder, gerne auch mit Werten.
Der Typ kann da auch angegeben werden, muss man
nicht.
Und Methodennamen
Ja, das ist sozusagen, wie wir es hier jetzt
so als Konvention machen, er ist ja eins und auch in SE2.
Das ist meistens interessant, dass dann tatsächlich, wenn man sich Objektdiagramme anguckt,
dann will man auch sehen, welche Werte sind denn wirklich drin.
Hier ist mal ein Beispiel für ein Projekt,
was ich sonst eigentlich immer zu Anfang zeige.
Hier, Tick-Tac-Toe. Ich muss hier mal eben,
ich habe jetzt, glaube ich,
nicht mehr die Zeit, das noch groß zu erläutern,
warum ich hier immer so auf und zu falten kann.
Also, das ist was, was ich in den Übungen
auch bearbeiten werdet. Es gibt hier eine Gui,
die euch ein Tick-Tac-Toe-Feld visualisiert
Und jetzt kann man hier tatsächlich TikTok-Toe spielen.
Ich spiele an dieser Stelle immer sehr gerne gegen das Publikum,
weil ich bin ungeschlagener Tech-Tac-Toe-Meister.
Das heißt, ich setze jetzt hier mal einen Stein hin.
Und jetzt könnt ihr mir zurufen, wo ihr hinsetzen wollt.
Und ich nehme das dann auf. Links oben,
links oben, links oben, da, okay, okay.
Ja, okay, dann setze ich mal hierhin.
Wo soll ich jetzt für euch hinsetzen?
Hier. Okay, okay, okay, okay.
Ja, okay, okay, okay. Ja,
okay, dann setze ich jetzt mal hierhin.
Okay, wo
Unten links. Unten links. Seht ihr? Ich gewinne
immer. Ich habe es ein bisschen mit den Ohren,
aber ansonsten geht es mir gut. Ja, gut.
Das ist TikTok-Toe. Das werdet ihr nicht in dieser Form
bekommen, sondern ihr müsst es zu Ende implementieren.
Ich zeige das deshalb,
weil wir hier ein Beispiel haben für so eine Modellierung,
die ich auf der Folie hier jetzt schon angedeutet habe.
Ihr sollt in der Klasse TikTok-Todi-Spiellogik implementieren. TikTok-Toe verwendet ein
Spielfeld. Also das Spielfeld, was ich hier gerade gesehen
habe, das kann ich ja nochmal aufrufen hier
Da ist die Gui. Das ist so ein Spielfeld und
ihr seht so ein Spielfeld von TikTok Tor,
hat drei Zeilen mit jeweils drei Zellen, kann man sagen.
So, und das ist tatsächlich hier auch so,
dass diese klassische Spielfeld genauso gebaut ist, die hat eine, besteht aus drei Spielfeldzeilen.
Das heißt, sie hält drei Exemplarvariablen, Zeile 0,
Zeile 1, Zeile 2, Zeile 0,
Zeile 1, Zeile 2 und in jeder Zeile,
in jeder Spielfeldzeile können halt bestimmte Positionen besetzt werden,
das können wir uns auch
nochmal angucken
Da gibt es dann hier sozusagen eine Spielfeldzeile und die hat dann einfach nur drei Zellen,
also hier Spalte 0, Spalte 1 und Spalte 2.
Und ich kann tatsächlich über so eine Spielfeldseite,
da kann ich jetzt sagen, setze mal,
was bei der Spielfeldzeile an die erste Spalte oder die zweite,
also in die nullte erste und zweite Spalte.
Und somit kriege ich dann, wenn ich drei von solchen Zeilen habe,
ein ganzes TikTok-Toe fällt. Und wenn man jetzt hier dieses Klassendiagramm sieht,
das ist ja ein Klassendiagramm,
gehe ich gleich noch genauer ein, die Klassendiagramme aussehen,
dann ist das, was auf der Folie ist,
hier, das ist jetzt das Objektdiagramm dazu.
Das heißt, Ich habe ein Spielfeld, ein Exemplar der Klasse Spielfeld,
die hält drei Referenzen in ihren Exemplarvariablen, auf Spielfeldzahlen,
also Exemplare der Klasse Spielfeldzeile.
Und das sind einfach Referenzen. Und dann hat man hier
Spielfeldzeile und Spielfeldzeile des Spielfelds, also drei Spielfeldzeilen,
die dann mit irgendwelchen Werten in den entsprechenden Zellen belegt sind.
Spiele 1 hat dieses Feld belegt, Spiele 2 hat dieses
Feld belegt und null heißt noch keiner der beiden Spiele hat das Feld besetzt.
So ist das in diesem kleinen Projekt gebaut
Und was man hier einfach wieder sieht, ist, in diesem Objekt hier,
da hat man drei Felder und die halten alle Referenzen,
diese Felder. Und diese, das sind Referenzvariablen,
das sind Exemplarvariablen und damit aber auch Referenzvariablen,
weil sie ja hier einen Referenztyp haben.
Und diese Varianten haben einen Namen, aber die Objekte,
die dahinter stehen, die haben keine Namen, die sind anonym.
Man könnte jetzt natürlich hier anfangen und sagen, hier,
zahle null reinschreiben, hier, Zeile 1,
hier zahle 2, weil das tatsächlich ja korreliert.
Aber das muss eben nicht so sein.
Also das ist einfach schlau in Java,
den Namen wegzulassen
Sonst kommt man relativ schnell in Teufelsküche. Okay. Also
da ist so viel zum Objektdiagramm. Objektdiagramme sind nützlich,
um einen Ausschnitt aus dem Objektgeflecht zur Laufzeit zu visualisieren.
Da müsst ihr euch klarmachen, so ein Java-System,
wenn das läuft, das sind nicht hunderte,
das sind nicht tausende, das sind Millionen von Objekten.
Das ist wirklich viel Zeug, was da passiert.
Hinter den Kulissen auch. Also es sind wirklich
ziemlich viele Objekte, wenn ihr ein Java-Programm schreibt.
Und man will aber genau das, was wichtig ist,
will man ja visualisieren. Und das ist sozusagen die Kunst,
die richtigen Diagramme zu malen, um deutlich zu machen,
wie sie denn so etwas zur Laufzeit aussieht.
Also es geht da viel darum,
zu kommunizieren über Objektsysteme
Okay. Dann gibt es sowas, was eher möglich ist,
aber eher unüblich ist, nämlich ich kann tatsächlich auch Klassen-
und Exemplare in einem Diagramm mixen, das ist eher ungewöhnlich.
Also hier sieht man irgendwie zwei Girokonto-Exemplare von der Klasse Girokonto
und man sieht hier irgendwie, die haben konkrete Werte,
also die Felder sind irgendwie konkret belegt und die sind aber irgendwie Exemplare von dieser Klasse.
Und man sieht hier zum Beispiel bei der Klasse sind jetzt hier
auch wieder diese beiden horizontalen Striche und dazwischen steht nichts,
also da ist einfach mal weggelassen,
dass die Dinger auch Felder haben, man möchte deutlich machen,
naja, so ein Girokonto ist primär definiert über seine Methoden,
der Umgang ist definiert und Exemplarvariablen sind versteckt.
Deswegen kann man das auch gut mal weglassen. So,
aber das macht man eigentlich nicht, sondern man hat entweder Objektdiagramme oder reine Klassendiagramme.
Bei dem Klassendiagramm ist es eigentlich sehr analog zu dem,
was ihr bei den Objektdiagrammen jetzt auch schon gesehen habt.
Hier oben steht der Klassenname, klar, wir reden über Klassen,
nicht mehr über Objekte. Dann die Felder mit den Typen,
da geht man üblicherweise keine Belegung an, es sei denn,
es ist tatsächlich eine Default-Belegung irgendwie vorgesehen,
aber das ist meistens auch nicht schlau,
das da mit reinzumalen.
Da gibt es Methodennamen und dann tatsächlich hiermit oder ohne Parametertypen,
auch da wieder erst der Name Doppelpunkt,
dann der Typ
Und wenn so ein Ding was liefert, wie zum Beispiel Gibsaldo,
da müsste da eigentlich jetzt auch Doppelpunkt und dann Int dahinterstehen
zum Beispiel oder Betrag an dem an der Stelle.
Das heißt also auch, der Ergebnistyp wird dahinter geschrieben,
also auch anders als in Java.
Das ist halt die Syntax von UML.
Ihr seht schon verschiedene Sprachen, verschiedene Syntaxen.
Ja, dann haben wir noch mal ein zweites Beispiel.
Das kennt ihr noch aus der allerersten Fulsi,
da habe ich ein bisschen was erzählt oder so ein Bankautomat-Beispiel.
Ja, also hier Bankautomat, Kontoverwaltung und die Kontoverwaltung hält Konten.
Da sieht man hier, dass das hier eine durchgezogene Linie ist.
Das ist eher so eine richtig stabile Beziehung,
also eine Kontoverwaltung hält oder enthält ein Konto ein Auto enthält einen Motor.
Und der Bankautomat benutzt die Kontoverwandtung, das ist eher eine
schwächere Beziehung, das ist also hier die Benutztbeziehung.
Die schwächste Beziehung der UML ist immer so eine gestrichelte mit so einem Pfeil.
Und dann wird hier das Girokonto benutzt und dann kann man
auch sowas haben wie Vererbungspfeile hier ist ein.
Also ein Girokonto ist ein spezielles Konto. Vererbung gucken wir uns
erst ausführlich an im nächsten Semester. Also einmal die Benutzbeziehung,
die schwächste Beziehung, dann enthält verwaltet,
das ist eher eine engere Beziehung,
also sowas wie ein Motor besteht aus,
ein Autobesteht aus einem Motor und einem Chassi und ähnliches.
Anderes Beispiel, noch ein UML-Diagramm, ein Klassendiagramm,
Sparbuch mit Zinssatz und Saldo,
Okay, dann die Attribute, die Operationsnamen.
Und dann gibt es sowas wie hier Zinssatz.
Also anscheinend hält so ein Sparbuch auch einen Zinssatz,
der einen bestimmten Wert hat und dann hat man hier die Operation auf dem Zinssatz.
Auch das ist hier jetzt eine enge Assoziation, also strukturelle Beziehung zwischen den Werten.
Und dann kann man aber auch sagen, naja,
aber in Methoden, da wird der Zinssatz nur benutzt.
Also dass hier halt wieder nur etwas schwächere Beziehung, eine Abhängigkeitsbeziehung zwischen Objekten.
Okay, das ist jetzt zusammengefasst nochmal das, was wir
über die UML gelernt haben. Das ist nicht viel.
Ihr werdet aber in den Übungen von uns immer wieder darauf hingewiesen werden,
dass wir doch mal wissen wollen, wie ihr so in der Lage seid,
auch mal so ein Klassendiagramm zu zeichnen.
Was ich sehr empfehlen kann,
ist dieses Buch hier von Martin Fauler, UML, Distillt,
ein sehr dünnes Buch, sehr knapp, sehr präzise beschrieben,
wofür OML gut eingesetzt werden kann und auch eher kritisch gegenüber diesen ganzen anderen Ansätzen.
Okay, wir sind jetzt fast durch, aber ich habe
natürlich noch ein bisschen was mit Storesi mit euch vor.
Ganz kurz. Ich habe hier in BlueJ ein Projekt,
das muss ich euch nochmal eben zeigen, Das ist das sogenannte Testszenario.
Ich habe einen Klienten, der benutzt eine Klasse Fahrzeug,
eine Klasse Chassis und eine Klasse Motor.
Der Motor ist ganz einfach definiert, hat eine Exemplarvariable von Tybulien.
Ich kann dem am Anfang im Konstruktor einen Anfangswert geben,
dem Motor, ob er läuft oder nicht.
Ich kann den Motor umschalten. Ich kann ja sagen,
läuft, läuft nicht. Also ich kann sozusagen immer umschalten
. Und ich kann ihn fragen, ob er läuft.
Also hier eine sondierende Operation. Okay,
ich versuche das mal ganz schnell zu memorieren.
Haha, das ist jetzt nicht so einfach.
Dann habe ich eine weitere Klasse
sehr einfach.
Die hält eine Exemplarwajahle von Typ Int. Da kann ich
auch einen Konstruktor angeben, welche Farbe die haben soll.
Also eine Int einfach als eine Kodierung für eine Farbe.
Es gibt also anscheinend hier 4 Milliarden,
2 Milliarden Farben, sagen wir mal. So,
und dann kann ich also tatsächlich hier diese Farbe speichern.
Dann kann ich diese Farbe erhöhen, erhöhen um ein Delta.
Ich kann also irgendwie sagen, die Farbe soll verändert werden.
Kann ich also hier sagen, Farbe ist gleich Farbe plus Delta.
Und ich kann auch wieder mit einer sondierenden Operation
die Farbe abfragen, also den Int abfragen.
Also eigentlich haben wir zwei ganz einfache Exemplare von diesen Klassen.
Einmal die, die einen Int haben und einmal die,
die einen Boo enthalten. Okay, und ich kann die auch abfragen.
Dann gibt es die Klasse Fahrzeug Und die sieht so aus,
die hat eine private Exemplarvariable C für einen Chassis und für einen Motor.
Also ein Fatrick setzt sich zusammen aus einem Chassis und einem Motor.
Und ich kann natürlich jetzt so ein Fahrzeug mehr erzeugen,
indem ich einen Chassis und einen Motor in den Konstrukt da reinstecke.
Und dann habe ich hier jetzt Operationen auf einem Fahrzeug.
Ich kann sagen, gib mir mal die nächste Farbe,
erhöhe einfach hier. Dann wird an dem Chassis erhöhen
um eins aufgerufen, also die nächst höhere Farbe gesetzt.
Und dann gibt es sowas wie Zündungstaste drücken.
Es gibt ja so Autos, wo man drückt,
also so BMW zum Beispiel, sollte man drauf,
dann wird der Motor angeschaltet,
wenn man nochmal drüber gewillter ausgeschaltet.
Wird also hier an dem Motor
einfach umschalten aufgerufen
Und dann kann man wieder sondieren, gib mir die Farbe,
dann wird die Farbe der Chassi rausgegeben.
Oder es kann man fragen, ob der Motor läuft,
indem man einfach den Motor fragt, ob er läuft.
Das ist schon ein relativ kompliziertes Projekt, ich weiß.
Jetzt gucken wir uns mal den Klient an, der das benutzt.
Der erzeugt sich zwei Chassis. Dann erzeugt er sich zwei Motoren.
Dann erzeugt er sich zwei Fahrzeuge und dann werden diese beiden Fahrzeuge manipuliert.
Also man macht hier irgendwie nächste Farbe, Zündungstaste drücken und so weiter.
Und am Ende wird jetzt sondiert, also in welchem Zustand sind diese Fahrzeuge?
Guckt euch diesen Code gründlich an. Ich stelle da jetzt
eine Frage zu. Ich kann den Code auch hier irgendwie hoffentlich
so ein bisschen links daneben stehen lassen, dass ihr das irgendwie seht.
Das ist die Methode, die ihr als benutzenden Code im Kopf haben müsst.
Und die Frage, die ich dazu habe, ist,
welchen Wert hat Farbe 1 zum Schluss?
Also, wenn ihr jetzt hier euch das anguckt,
hier seht ihr die lokale variable Farbe 1,
die kriegt ihren Wert von F1, gibt Farbe.
So, und jetzt starte ich die Abstimmung,
jetzt könnt ihr da ein bisschen drüber nachdenken,
ob ihr jetzt 42, 43.000 oder 1001 sagt,
Ich vermute mal, lasst euch da Zeit mit,
das ist nicht so ganz einfach.
Mal gucken, ob da schon was kommt.
Die Stimmen kommen noch sehr vorsichtig.
Ihr seht schon, es geht darum, irgendwie mit den
Referenzen klarzukommen. Da sind also jetzt Objekte miteinander verwoben.
Ist also nicht so ganz einfach. Okay,
ich gucke mal, was jetzt hier so 172 Stimmen wunderbar.
Ich beende das. Jetzt hoffe ich mal, dass ich
jetzt wieder mir jemand das zerschossen habe mit irgendeinem invaliden Wert.
Die Verteilung sieht so aus, B43. Das ist wunderbar,
weil das ist nämlich auch die richtige Antwort.
Traumhaft. Das war auch noch einfach.
Das war auch noch einfach. Schwieriger ist diese Frage
Welche Werte haben Pferd 1 und Pferd 2 zum Schluss?
Also das sind diese beiden bullschen Variablen. Hier unten Pferd 1
und Pferd 2. A, beide sind Falls, B,
Fährt 1 ist True Fair 2 ist Falls, C,
Fährt 1 ist Falls, Pferd 2 ist True und D,
beide sind True.
Das ist ein
ziemlich gemeines Ding
Ach, ich habe die Abstimmung noch gar nicht gestartet.
Entschuldigung. Jetzt könnt ihr euch nochmal entscheiden.
Hab lang genug Zeit gehabt, darüber nachzudenken.
Jetzt kommen hier die Antworten relativ schnell.
Ja, hier ist der Code.
Ja. Okay, ich beende das, 172 Stimmen.
Ich gucke mal auf das Ergebnis. Nein,
ich gucke ja nicht, ob das hier,
ich gucke erst mal auf das hier.
Das ist eine ziemliche Gleichverteilung. Oha. Beziehungsweise es ist hier so
ein bisschen so, Pferd 1 ist True Fat 2 ist Falls.
Okay. Was passiert hier? Das Gemeine liegt hier.
Hier steht M2 und hier steht auch
Ja. Das ist das Gemeine bei Software. Man muss
wirklich sehr genau hingucken. Was ich nämlich gemacht habe,
trickigerweise, ich habe den Motor 2 in beide Fahrzeuge
gesteckt und den Motor 1 ist überhaupt nirgends beteiligt.
Das heißt, Motor 1 wird nicht verändert. Das heißt,
der bleibt true, Motor 2 wird hier Zündungstaste drücken,
wird auf False gesetzt.
Das heißt, wenn ich die Fahrzeuge frage,
dann sind die beide false
Das heißt, die richtige Antwort sollte sein, beide sind Forts.
Ja, sehr schön. Ich freue mich,
dass ich euch aufs Glatteis geführt habe.
Damit machen wir Schluss für heute.
Vielen Dank