1, 2, 3. Einen wunderschönen guten Tag.
Meine Namen und Herren, zur letzten Vorlesung des Jahres
2014. Jedenfalls die letzte SE1-Vorlesung und es freut mich natürlich
ganz besonders, dass Fred auch wieder unter uns weilt.
Das heißt, heute kriegen sie wieder mit flinken Fingern an
der Tastatur Konzepte der objektorientierten Programmierung in Java nahe gebracht.
Das Thema der heutigen Vorlesung sind sogenannte Objektsammlungen
Ja. Also bis jetzt ist es ja so,
ich will nicht sagen, vergleichsweise langweilig, womit man sich so beschäftigen kann.
Aber das Große, ja, das große Problem. Also eins der Probleme,
mit denen wir uns so rumschlagen können, müssen, ist,
wenn wir so mal mit zwei oder vielleicht sogar drei gleichartigen,
gleichen Objekten umgehen wollen, was machen wir denn dann?
Die Möglichkeit, die wir bis jetzt kennengelernt haben,
ist, wir deklarieren eine Variable Kunde 1,
Kunde 2, Kunde 3 und dann müssen wir halt mit
diesen drei Variablen umgehen
Aber wenn man mal so etwas näher hinschaut,
eigentlich hätte man ganz gerne so eine Datenstruktur,
eine Sammlung von Objekten, die es einem ermöglicht,
also gleich mit so einer, jetzt sage ich schon mal,
Menge oder einer Liste von gleichartigen Objekten umzugehen.
Und wie wir das konzeptionell hinbekommen und in Java umsetzen,
das ist das Thema der heutigen Lehrveranstaltung.
Ich habe in den Vorlesungsvorlien habe ich verschiedene Smilies untergebracht,
bei diesen Vorlesungen insofern ganz hübsch ist,
weil sie doch ein paar Themen aufgreift,
die wir so in den vergangenen Wochen so aufgesammelt haben.
Wie wir diese Vorlesung sammelt, diese Themen auf.
Also dazu gehören insbesondere Interfaces, aber auch so das Konzept
der Rekursion, das nur ganz wenig.
Aber wir werden uns anschauen, also wie wir diese Themen,
über die sie, über die wir schon gesprochen haben,
welche Bedeutung die im Rahmen von im Rahmen des Umgangs mit Objektsammlungen haben.
So, einen Satz wollte ich
noch hier besonders hervorheben
So, sie werden jetzt insbesondere, wird das Konzept,
also der Interfaces, mit dem wir uns letzte Woche beschäftigt haben,
wird, denke ich, an dieser Stelle,
spätestens an dieser Stelle wird es unmittelbar einsichtig,
warum das sinnvoll ist, Interfaces, Spezifikation von etwas,
die Spezifikation eines Typen und die Implementation voneinander zu trennen.
Es ist also gerade beim Umgang mit Sammlungen,
spielt dieses Konzept eine wesentliche Rolle.
Zwei Arten von Objektsammlungen werden wir uns etwas detaillierter anschauen,
wir werden gleich auch noch eine ganze Menge von unterschiedlichen Objektsammlungen kennenlernen.
Zwei haben für die Programmierung nicht nur in Java,
sondern für die Programmierung im Allgemeinen, haben eine besondere Bedeutung.
Und das ist das Konzept der Menge und das Konzept der Liste.
Was ist das? Was wollen wir darunter im Weiteren verstehen?
Listen zunächst mal so näherungsweise Definition,
lineare Sammlungen von gleichartigen Elementen, in denen ein Element
mehrfach auftreten kann
Kreisfrage, welches von diesen beiden Schaubildern repräsentiert eine Liste?
Die Antwort darauf lautet dieses hier. Das ist eine Liste,
das ist also eine lineare Sammlung. Welches Element kommt mehrfach vor? Och man,
das ist also, da braucht man, glaube ich,
noch nicht mal als Hochschulreife für, das hat so mehr so Sesamstraßenniveau.
Also dieses Element kommt mehrfach vor, das ist per Definition
ein wunderbares Beispiel oder nach der Definition ein wunderbares Beispiel für eine Liste.
Und genauer eine lineare Liste. Das hier ist ein Beispiel für eine Menge,
wie ist das definiert im Weiteren, eine ungeordnete Sammlung von Elementen,
in denen jedes Element höchstens einmal vorkommt, also keine doppelten Elemente.
So, das soll uns jetzt erst mal so als näheres,
zunächst mal als Verständnis ausreichen, um das so grundsätzlich klarzukriegen,
mit welchen beiden Arten von Sammlungen wollen wir uns im Weiteren beschäftigen.
So, etwas genauer hingeschaut, wie eine Liste, wie eine Liste, definiert ist.
Nun, oder wie mit ihr nachher umgegangen wird,
insbesondere hat also bei der Liste, spielt es eine Rolle,
dass die Elemente eine bestimmte Reihenfolge haben.
Jetzt können Sie schon anfangen zu überlegen für Problemsituationen,
die Sie mithilfe eines Programms bewältigen wollen,
Sie werden regelmäßig vor der Entscheidung stehen,
welche Art von Sammlung will ich verwenden,
um mein Problem adäquat zu modellieren, um mein Problem adäquat zu lösen.
Und dann kann man halt,
wir werden diese Liste von Kriterien jetzt gleich mal durchgehen,
wenn Sie eine Problemstellung haben, wobei die Reihenfolge der Listenelemente,
also die Art und Weise, wie die Solistenelemente verwaltet werden,
eine Rolle spielen, dann steht die Liste,
dann ist die Liste ein Kandidat.
Die Menge ist dann kein Kandidat,
weil in der Menge die Reihenfolge der Elemente
bedeutungslos ist
Definition. Ebenfalls, das hatten wir schon gesagt,
dass ein Wert mehrfach in der Liste vorkommen kann.
Hier jetzt der Bezug zur Rekursion, wie ist eine Liste im einfachsten,
und man könnte auch sagen, im elegantesten Fall definiert.
Nun, eine Liste ist entweder eine leere Liste,
das ist für Nicht-Informatiker und Nicht-Mathematiker,
ist das häufig so der schräge Teil der Definition.
Also, dass eine leere Liste ist eine Liste und das
ist der einfache Fall, das ist der Rekursionsabschluss.
Oder eine Liste ist ein Listenelement,
gefolgt von einer Liste
Das kann man sich jetzt also so vorstellen.
Entweder die Liste ist leer oder ich habe ein Listenelement,
gefolgt von einer Liste und diese Liste kann entweder leer sein oder sie kann wieder eine Liste sein,
gefolgt von einem List, von einer Liste,
die entweder leer ist oder ein Listenelement hat.
Wenn ich die Zeit jetzt füllen wollte,
könnte ich bis mindestens Viertel vor 4 noch beispielhaft,
also diese Liste weiter aufbauen, aber vom Grundprinzip her wird
sich nichts ändern und irgendwann werden sie sich auch fragen,
muss das sein?
Das ist ja jetzt auch, dass es 258. Listenelement hier
rekursiv definiert. Nein, das muss nicht sein.
Was kann man mit so einer Liste tun
So eine Art des Umgangs mit einer Liste. Sie erinnern sich,
Umgang, ist also nichts, also es ist im Umgangssprachlichen,
haha, ist das etwas so zwischen uns,
aber Umgang mit einem Objekt bedeutet, es gibt sondierende und verändernde Operationen,
auf diese Unterscheidung werde ich gleich auch noch mal zu sprechen kommen.
Ein Element oder eine Art des Umgangs mit einer Liste ist,
dass man sie sequenziell, den Begriff werden sie jetzt auch häufiger hören,
dass man sie sequenziell iterieren kann, iterieren bedeutet,
ich schaue mir jedes Element der Liste an und zwar in einer sequenziellen Reihenfolge.
Das ist eine Art, seine typische Art des Umgangs,
ich schaue mir jedes Listenelement an und ich fange beim ersten
an und ich höre beim letzten Element auf.
Jetzt bin ich sehr dankbar, dass Axel Schwolitzky,
also mein Vorgänger hier in dieser Vorlesung,
hat sehr viel Liebe und Mühe verbracht, damit verbracht,
diese Folienanimation herzustellen,
die natürlich so in der ausgedruckten Fassung überhaupt nicht zum Tragen kommt.
Also was kann man mit Listen tun? Das Beispiel dazu ist
eine Liste von Namen, die für eine Pausenaufsicht vorgesehen sind.
Sie sehen diese Liste von Namen hier,
das erste Element in der Liste ist Peter.
Dann kommen die anderen
Ach, und... Eins der vielen Programmierprobleme im Alltag,
im Umgang mit Listen besteht darin,
dass das erste Listenelement in vielen Programmiersprachen,
unter anderem auch in Java, den Index null hat.
Wenn ich also auf das erste Misstenelement zugreifen möchte,
dann ist das das nullte Element in dieser Liste.
Was dazu führt, dass also,
weil wir alle ein plus-minus-eins-Problem haben, wir die Softwareentwickler diejenigen sind,
bei denen es immer auffällt, dass wir ein Plus-minus-eins-Problem haben.
So, nach dem Motto, wie viele Elemente hat diese Liste?
Ja, ist doch klar. Fünf. Was ist der Index
des letzten Elementes? Ist auch klar. Vier. So,
da fragt man sich natürlich, wieso ist es eigentlich so?
Wieso hat also das erste Listenelement nicht den Index 1 und
das letzte Listenelement den Index 5?
Die Frage darauf kann ihn vielleicht Fred beantworten. Ich kann
da höchstens mal in die Geschichte der Programmiersprachen kurz greifen,
argumentativ, wenn man sich ein Bild des Hauptspeichers vor Augen führt.
Und man möchte auf das erste Listen-Element zugreifen,
dann hat das den Offset null.
Das ist halt hier ganz unten im Hauptspeicher.
Und das zweite Listen-Element hat einen Offset, der berechnet wird.
Wie groß ist das erste Listen-Element? Und das hat dann
eben, da muss man schon was ausrechnen. Das heißt,
der Zugriff auf das erste Listen-Element kann ohne Berechnung stattfinden.
Während wenn man das Listen-Element 1 indizieren würde,
müsste man da schon einen zusätzlichen Rechenschritt durchführen.
Und das war wohl in Zeiten, in denen Rechenzeit
noch ein echtes Problem gewesen ist.
Das ist heutzutage auch noch ein Problem
Aber eigentlich eher für eine kleine Klasse von Problemen.
Eine Überlegung, die dazu geführt hat. Weitere Ausführungen zu
dem Thema hast du auch nicht. Na dann, bitte.
Das Thema ist das für die Leute, die jetzt schon sprechen,
Stücke verloren haben, die hat es bestimmt schon bemerkt,
dass Speicher im untersten Level ganz natürlich mit null Beginn humorieren.
Tja. Ihr seid etwas intuitiv, da auch anzufangen.
Also für diejenigen von Ihnen, die schon Rechnerstrukturen hören,
sagt ihr Kommilitone, sei es natürlich auf der untersten Ebene mit null zu adressieren.
Ich finde es unnatürlich, Aber ich höre auch im Moment nicht Rechnerstrukturen.
Ja, also was da natürlich, also in der ehemaligen
DDR soll man drei Arten von Wissenschaften unterschieden haben.
Natürliche Wissenschaften, unnatürliche Wissenschaften und kontranatürliche Wissenschaften. Das war dann Marxismus,
Lenidismus, weil das einzige Beispiel dafür, ich weiß nicht,
in welcher Klassifikation die Informatik da fällt,
aber natürlich ist bei uns eigentlich nichts.
Das ist also mindestens unnatürlich, womit wir uns hier beschäftigen.
So, jetzt einfügen an zweiter Position.
Was passiert da jetzt? Ist es nicht schön
Boah, haben Sie das gesehen? Und jetzt? Plonk. Ja,
also dank an Axel Schmolitzky für diese Animation. So,
einfügen an der zweiten Position, ist jetzt aber insofern bemerkenswert,
als dass da etwas passiert, um mal darauf zurückzukommen,
was ich jetzt erstmal unnatürlich finde, dass nämlich die Element,
das Element, das hier vorher stand, nämlich Paul und die darauf folgenden,
dass das alles um eins nach rechts verschoben worden ist.
So, was ich genauso natürlich gefunden hätte, wäre,
wenn Paul einfach durch Jahren ersetzt worden wäre
Also die Anzahl der Elemente gleichgeblieben wäre. Und jetzt kommt
der menschliche Anteil an dieser Diskussion. Es ist für,
sie werden eine Reihe von diesen Interfaces kennenlernen.
Und dann gibt es da zum Beispiel die Operation Ad.
So, eine verändernde Operation an einer Sammlung. So,
Ad hört sich jetzt erst mal so an, ich füge etwas hinzu.
So, natürlich. Aber was füge ich jetzt hier zu
und was bedeutet das? Natürlich füge ich das Element hinzu,
das ich jetzt als Parameter übergebe. Aber überschreibt es das Element,
das bereits vorher da gewesen ist oder ersetzt es das?
Und alle anderen werden um eins nachgedacht
Rechts, also sprich zu einem etwas höheren Index verschoben.
Das sind so die Fragen, die sich der Programmierer,
sie dann in weiteren Stellen muss. Also wie ist diese,
wie ist das genau definiert, spezifiziert,
was da als Operation so mit dem harmlosen Namen at daherkommt.
So, wie sieht das jetzt aus? Wir haben ein
Element mehr und jetzt wollen wir das zweite Element entfernen.
Also an der Animation könnte ich fürs nächste Jahr mal noch ein bisschen arbeiten.
Das könnte so Apple-mäßig noch ein bisschen langsamer gehen.
Und jetzt sind die Indizes halt so
Für dieses Beispiel. Wunderbar. So, das zum Thema List
, jetzt zum Thema Menge. Was ist eine Menge?
Wer von Ihnen hat noch Mengenlehre in der Schule gehabt?
Da müssen Sie ungefähr zum selben Zeitpunkt wie ich zur Schule gegangen sein.
Ich hatte das in Klasse 5 oder 6,
also diese Modewelle ist auch irgendwann mal abgeschwappt.
Also das sehe ich jetzt, wenn sich so wenige Leute melden.
Na gut, also mal ganz kurz,
was ist der Anteil von Mengenlehre, den wir brauchen,
für die Programmierung.
Was ist erstmal eine Menge? Ich hatte es schon gesagt,
eine Sammlung von gleichartigen Elementen
Element kommt nur einmal vor. Falls die Elemente doch mehrfach vorkommen,
heißen die dann Multimengen oder Englisch-Back. Von mir aus.
So, das Englische, die ganzen Schnittstellen, Interfaces,
die sie kennenlernen, sind natürlich alle in englischer Form.
Und das sind so die typischen Operationen, die auf Mengen durchgeführt werden können,
ein Element hinzufügen. So ist noch nicht vorhanden ist,
ein Element aus der Menge entfernen, eine Prüfung,
eine sondierende Operation, ob ein Element in der Menge vorhanden ist.
Vereinigungsmenge, Schnittmenge, Differenzmenge und die Prüfung, ob eine Menge leer ist.
Weil Differenzmenge musste, also gut, Vereinigung zweier Mengen,
ist klar, alles in eine Menge hinein,
bis auf die doppelten Elemente, Schnittmenge,
welche Elemente sind in beiden Mengen enthalten und die Differenzmenge,
welche Elemente sind in A, aber nicht in B enthalten.
Das kann man also,
muss man sich vielleicht auch nochmal in der Mathematik irgendwo nachschauen,
wie das genau definiert ist,
aber das ist so die Definition davon,
so ein paar von diesen Operationen werden wir brauchen und
die sind auch alle ihre Implementation,
ist in den Interfaces beschrieben
So, was kann man mit Mengen tun,
so wie ich Beispiele für den Umgang mit Listen vorgefunden habe,
beziehungsweise gezeigt habe, kann man auch mit Mengen,
also das ist ja alles so immer unter dem Gesichtspunkt,
Mengen und Listen sind Beispiele für Sammlungen,
was sind so typische Anwendungen für Mengen,
hier sehen Sie, das Anwendungsbeispiel, Textanalyse,
also wie will ich einen Textsammlung von Wörtern,
wie will ich den abbilden?
Naja gut, ich könnte den als Liste von Wörtern implementieren,
also mit dem Instrumentarium, das ich ihnen gerade gezeigt habe,
alternativ, je nachdem, welche Fragestellung wir haben,
könnten wir einen Text, aber auch als eine Menge von Wörtern betrachten.
Was möglicherweise nicht so adäquat ist,
wenn wir das Ding von vorne nach hinten lesen wollen,
weil die Menge ja eine Ungeordnete, keine Ordnung hat über den Wörtern,
also den Text so zu lesen,
dass er nur eine Menge von Wörtern darstellt, ist wohl unangebracht.
Aber wenn uns primär interessiert, welche Wörter verwendet werden,
dann können wir den durchaus mal als Menge betrachten.
Dann kann man sich so Fragen beantworten,
welche Wörter sind sowohl in Text 1 als auch in Text 2
enthalten und wir können Füllwörter versuchen zu identifizieren.
Wir können die Schnittmenge bilden, also Fragen dieser Art beantworten.
Sodass die Essenz an diesem Beispiel ist eigentlich an diesem verschiedenen
für sich genommen vergleichsweise irrelevanten Beispielen, ist eigentlich,
sie haben nachher die Entscheidung, sich eine Datenstruktur auszusuchen,
die für die Lösung ihres Problems adäquat ist.
Und das ist im Zweifelsfall immer eine Abwägung zwischen zwei verschiedenen Übeln,
aber sie sind diejenigen, die begründet zu begründen haben,
warum sie sich für eine bestimmte Implementation für eine bestimmte Datenstruktur
zur Lösung ihres Problems
entschieden haben
Ein Konzept, das im Zusammenhang mit Sammlungen
eine Bedeutung hat, sind sogenannte Maps, Deutsch-Abbildungen.
Das sind Mengen von sogenannten Schlüsselwertpaaren. Diese Idee hinter Schlüsselwertpaaren ist,
dass ich eine Menge von eindeutigen Schlüsseln verwende,
um über einen Schlüssel an einen bestimmten Wert oder eine Menge von Werten zu kommen.
Das ist ein sehr effizientes Suchverfahren,
insbesondere auf so Mengen unter der Voraussetzung und das
ist die Voraussetzung für Abbildung
Maps, dass die Schlüssel eindeutig definiert werden können. Sie sehen hier so das Beispiel,
das ist jetzt mittlerweile auch schon so ein bisschen ein Telefonbuch,
gibt es ja auch auf diesem modernen Endgeräten, also unter der Voraussetzung,
dass es einen eindeutigen Namen gibt, kriegen wir als Ergebnis für eine solche Abfrage eines eindeutigen Schlüssels, kriegen wir eine Menge von Werten und das ist halt eine Menge von Telefonnummern.
Die Sprachbildung ist also hier wieder mit dem Smiley für das bekannte Konzept,
das wir schon Konzept, das wir schon kennengelernt haben,
für den Klienten einer Abbildung, ist es wichtig,
dass ihr einen eindeutigen Schlüssel über einen eindeutigen Schlüssel verfügt und dann bekommt er in relativ kurzer Zeit oder sehr effizient,
bekommt er ein Ergebnis, nämlich welcher Wert,
welche Wert T sind mit diesem Schlüssel verbunden,
so in den Beispielen, die wir,
das ist nochmal in Bezug zu den Beispielen,
die sie gerade gesehen haben, also die Abbildung von Wörtern auf ihre Häufigkeiten,
dann ist der Schlüssel ein eindeutiger String und wir bekommen also als Wert dieser Abbildung bekommen wir die Anzahl der Wörter oder diese etwas kompliziertere Abbildung,
dass auf Basis seiner Häufigkeit eine Menge von Wörtern genannt wird,
dass jetzt gesagt wird,
welches Wort kommt also eigentlich wie oft vor,
beziehungsweise mit welcher Häufigkeit sind welche Wörter in einem Text vorhanden.
So, ich habe jetzt schon als Oberbegriff für Mengen und Listen
, habe ich jemals den Begriff der Sammlung verwendet.
Das ist eine ganz beliebte Herangehensweise in der, gerade in der objektorientierten Programmierung,
diese Herangehensweise ist aber ansonsten auch in anderen Anwendungsbereichen durchaus üblich.
Man schaut sich Ausprägungen von Konzepten an. Also in unserem Fall
die Menge und die Liste. Und was man versucht zu generalisieren,
im Sinne einer Begriffsbildung ist, was haben diese Konzepte eigentlich gemeinsam?
Weil dann brauche ich nicht mehr über Mengen und Listen in unserem Beispiel zu sprechen,
sondern ich kann gleich den Oberbegriff verwenden, die Sammlung.
Und der Begriff der Sammlung ist ein Begriff,
der unter dem englischen Namen Connection, also gerade objektorientierten Programmiersprachen,
auch eine große Bedeutung hat in dem Sinne,
als das mit jeder objektorientierten Programmiersprache eigentlich vorimplementiert,
Menge von unterschiedlichen Sammlungen daherkommt, sodass sie für die Programmieraufgaben,
die sie in der Praxis zu lösen haben,
nicht immer gezwungen sind, also sich zunächst mal zu überlegen,
also ich muss mir eine Liste implementieren,
ich muss eine Menge implementieren und was ist sonst noch so an verschiedenen,
was an verschiedenen Sammlungen unterschieden wird.
So, diese Container-Bibliotheken stehen also auch in Java zur Verfügung,
das heißt,
hier wird Ihnen ein Angebot gemacht für eine ganze Reihe von Problemen,
die andere schon mal für Sie mit unter Verwendung von Collections
gelöst haben,
sich die passende Collection herauszuholen
Die Randbedingung ist so für die üblichen Collections.
Deswegen steht hier auch so Sammlungen enthalten in der Regel.
Objekte vom selben Typ. Das ist aber eine Randbedingung,
die für, sagen wir mal, für die allermeisten Probleme kein größeres Problem darstellt.
Das sind so die Arten von Sammlungen, die in Java
vorimplementiert sind, sodass sie die problemlos verwenden können.
So, für den Umgang mit Sammlungen, jetzt hatten wir schon
einen Umgang mit Listen, Umgang mit Umgang mit Mengen.
Da haben wir gesehen, da gibt es wohl Gemeinsamkeiten als
auch Unterschiede. Sind jetzt diese Randbedingungen hier von Bedeutungen,
die helfen Ihnen dann nachher auch,
also diese Liste von Kriterien hilft Ihnen auch,
sich die geeignete Sammlung für Ihr Problem herauszusuchen.
Also das ist zum einen, ist eine Reihenfolge oder keine
Reihenfolge für die Elemente der Sammlung definiert. Wenn eine Reihenfolge definiert ist,
sind Sie als der Benutzer der Sammlung derjenige, diejenige,
der diese Reihenfolge festlegt,
oder ist das eine automatische Reihe
Folge, die durch die Sammlung festgelegt wird. So eine automatische Reihenfolge,
wir haben das letztens in einer der letzten Vorlesungen mal,
also so ein Beispiel für einen Keller gesehen.
Das waren diese Äpfel, die so übereinandergelegt wurden.
Das wäre eine automatische Reihenfolge für die Elemente der Sammlung.
Nämlich, ich kann immer nur auf das Element zugreifen,
auf das ich zuletzt, also der Sammlung hinzugefügt habe.
Auf die Elemente, die ich vorher eingefügt habe,
kann ich nicht mehr zugreifen, so wie zum Beispiel bei der Liste,
wo ich auf jedes Element zugreifen konnte. Das heißt also,
wir haben auch bei den Sammlungen, die Reihenfolgen definierten,
definieren müssen wir nochmal unterscheiden zwischen denjenigen, die,
also deren Reihenfolgebedingungen wir selbst festlegen oder die durch ihre Definition eine automatische Reihenfolge definieren.
Also Keller ist ein Beispiel und das andere klassische Beispiel ist die Schlange,
also ich kann immer nur auf das, die Elemente,
in der Reihenfolge zugreifen, in der sie auch hinzugefügt worden sind.
Also das, was zuletzt zugefügt wurde,
kann ich auch zuletzt erst wieder rausnehmen.
Das ist die Schlange
So, der zweite Unterschied, das zweite Kriterium ist,
wie wird mit Duplikaten in den Sammlungen umgegangen?
Also das ist wahlweise zugelassen oder nicht zugelassen.
Und wenn man das mal soweit ausdifferenziert hat,
also diese zwei Eigenschaften mit ihren jeweils zwei bzw. drei Ausprägungen,
dann sehen sie hier schon eine ziemlich vollständige Liste von Sammlungen,
wie sie in Java zur Verfügung gestellt werden.
Und in Rot sehen sie die Sammlungen, mit denen wir
uns im Weiteren im Rahmen von der SE1 beschäftigen werden.
Jetzt kommen noch so ein paar Beispiele für für diese Anwendungsfälle,
für diese Arten von Sammlungen,
warum jetzt ausgerechnet die Bundesliga-Tabelle eine sortierte Menge ist und nicht nur sortierte Liste,
wäre mal eine kleine Diskussion wert, aber das lassen wir jetzt mal.
Also es gibt da wohl auch keine, nicht Wohlsein,
das kann man so oder so machen.
Also das kann man jetzt,
müsste man eine Menge von Kriterien definieren,
also warum eine Implementierung der Bundesliga-Tabelle als sortierte Menge adäquater ist
als eine sortierte Liste
Na, ein Argument könnte sein, ein Verein kann nur
einmal in der Liste, in der Menge enthalten sein.
Und deswegen ist die Randbedingung der sortierten Menge schon mal nicht schlecht
für die Bundesliga-Tabelle. So, jetzt kommen wir zur Überleitung
. Wie wird das Ganze in Java gehandhabt? Das,
was Sie jetzt für den Rest Ihres Programmiererlebens,
jedenfalls solange es durch Java geprägt ist,
begleiten wird,
ist das sogenannte Java-Collections-Framework
Oder einen kurzen JCF. So, hier finden Sie jetzt genau
die Unterscheidung wieder, die wir in der letzten Vorlesung motiviert haben.
Also sie und ich, wir, nicht wir, ich.
Und die besteht darin, dass so eine Reihe von Interfaces in diesem JCF definiert ist.
Und für diese Interfaces gibt es unterschiedliche Implementationen. Und diese Implementationen sagen Ihnen jeweils,
was sie besonders, also die können die implementieren natürlich,
alle jeweils, also eine Menge von Interfaces beziehungsweise Also umgekehrt ein Interface,
wenn jemand behauptet, er erfüllt er sie,
die Klasse erfüllt dieses Interface, dann tut es das.
Bloß, die machen das für unterschiedliche Arten von Anwendungen
unterschiedlich gut. Deswegen kann man sich entscheiden,
also wen man denn jetzt dieses Interface für das man sich entschieden hat,
wen man als Implementation vorsieht oder,
wenn sie so ganz besonders verwegen sind und sagen,
also habe ich nicht geschrieben, glaube ich nicht,
deswegen implementiere ich das lieber selbst.
Sie selbst können auch eine Implementation für dieses Interface vorlegen
Wie sehen die Standard-Interfaces für Menge und Liste aus?
So in Grün sehen sie jeweils die sondierenden Operationen und in diesem...
Wie sieht denn das hier aus? Rosa, Rosa.
Sehen Sie die verändernden Operationen? Oder die sondierenden Operationen für
den Set? Also das ist, wie gesagt,
wie es hier oben steht, ist nur ein Ausschnitt.
Ich kann also ein Set fragen, wie groß er ist.
Groß im Sinne von, wie viele Elemente sind da drin?
Ich kann den fragen, ob er leer ist und
ich kann fragen, ob er ein bestimmtes Element enthält
Bei den verändernden Operationen, ich kann was hinzufügen,
ich kann was wegnehmen oder ich kann diesen,
ich kann diese Elemente, diese Länge, diese Menge lehren,
also alle Elemente auf einmal aus dem Set entfernen.
Ja, weil ein Beispiel, keine Angst, Fred,
ich werde jetzt nicht Blue Jay auspacken, das Privileg,
überlasse ich dir. Nur mal so,
dass sie das hier mal gesehen haben, vor allem,
was den Unterschied zwischen nochmal zwischen dem Interface und der
implementierenden Klasse anbetrifft
Das hier ist die Angabe des Interfaces, das so für
das Objekt Babys unter dem Namen Babynamen referenziert wird, gewählt wird.
So Babynamen soll also eine Menge von Strings sein.
Set ist ein Interface. Die Implementation, die implementierende Klasse
ist dann, also es wurde hier gewählt als Hashset.
So da gibt es eine Reihe von Klassen,
wie gesagt, die, also denen,
die das Interface String implementieren und der Programmierer dieser Zeilen hat sich dafür entschieden,
jetzt ein Hashset als Implement zu wählen.
Und jetzt ist das folgendes hoffentlich eigentlich ganz geradeaus oder straightforward.
So, wenn ich über diesen, wenn ich weiß,
also welche Operationen bei diesem Set-Interface zur Verfügung stehen,
stehen kann ich mir also zunächst mal ein Bild davon machen.
Gut, wie groß ist denn dieser Set in dem Moment,
wo ich das Objekt erzeugt habe? Die hoffen,
die begründete Hoffnung besteht darin, dass diese Menge nach der Erzeugung leer ist.
So, dann fügen wir eins, zwei, drei,
vier Elemente hinzu, haben wir schon,
und das ist jetzt keine überraschende Antwort nach dem,
was ich Ihnen vorhin erzählt habe, da Anna das Duplikat ist,
wird es nicht hinzugefügt.
Und das muss man einfach wissen, wenn man sich,
also dieses Interface anschaut, wird man das dann auch lesen.
Dieses Element wird nur hinzugefügt bei dem Ausführen von Ad,
wenn es vorher noch nicht drin gewesen ist. So,
also das lesen Sie, lese ich auch schon fast wie die Zeitung,
wenn Julia, wenn Julia noch nicht drin ist,
dann wird Julia aufgenommen, Jannika wird weggenommen,
so wie groß ist die Anzahl dann wieder?
Warten Sie mal, hier war es drei,
Julia war noch nicht drin, vier, einen weg,
sind wir wieder bei drei.
Also mindestens für diese Art von Beispiel reicht es,
wenn man das zehn zählen kann.
So, dann sind wir wieder bei drei nach Clear.
Könnte man jetzt noch die letzte sondierende Operation hier hinzufügen,
das heißt, von Babynamen dürfte nach Aufruf von Clear wieder gleich Null sein.
So benutzt man Sets in Java. So,
jetzt fragt man sich,
ja bitte
Du wieder beantworten. Bulien. Vor allem,
wer das hier nicht so verwendet, wer meines Gottes vorsteht,
Bulien, wo der verändert ist. Ja,
mit der Kommilitone sagt, also völlig zu Recht,
es gibt hier, also die Spezifikation von Ad sagt,
also es wird True oder Vorrats,
wird hier zurückgeliefert
Und wenn ich das jetzt hier so lese,
würde ich sagen, okay, dass die Menge sagt mir,
hat es geklappt, dass dieses Element hinzugefügt wird.
Wenn es klappt, sagt es mir True und wenn nicht,
also zum Beispiel in dem Fall,
dass das schon drin war, dann sagt es halt Falls.
Also so würde ich mir das jetzt erstmal erklären.
Womit ich Ihnen aber auf jeden Fall recht gebe,
ist, so wie das hier steht,
müsste das nicht auf einen Compiler-Fehler hinauslaufen,
gibt es noch eine Operation Ad,
die kein Bulien ist,
sondern ein Volt
Aber das war wunderbar, glaube ich. Deine Vermutung war
richtig, endlich mal zurück, ob es geklappt hat.
Ja, aber wie kann das da jetzt verwendet werden,
ohne dass man den Rückgabewert von Ad verwendet?
Weil Java einfach so lastudiert ist. Haben Sie das gehört
? Ich fragte Fred an, wie kann das sein,
dass der Compiler da keinen Fehler meldet und der argumentiert mit der Laschheit der Definition von Java.
Aber danke für den Hinweis. Weil eigentlich Nach der Spezifikation müsste jetzt hier nämlich stehen, If,
Klammer auf, babynamen.at, wenn offensichtlich war der Name noch nicht drin,
deswegen ist er jetzt drin, Else war wohl schon drin.
Danke. So, Equals. Ach du, Jubiläum.
Wozu ist das gut? Es ist zum Beispiel gut,
um feststellen, wenn ich mich mal in die Rolle einer Menge versetze,
wenn jemand mir ein Element hinzufügen möchte und ich aber per Definition
keine Element zweimal in mir zweimal das gleiche Element in mir enthalten haben möchte,
dann muss ich dieses mir übergeben Element mal fragen,
ob es schon einem ähnelt,
das schon in mir drin ist.
Deswegen kann man jedes Objekt in Java fragen, ob es
einem anderen gleich ist. Und das ist eine,
warum das so ist, warum man das fragen kann.
Das letzte Geheimnis, dazu werden wir erst in SE2
lösen für den Moment
Also haben sie vielleicht in Blue J auch schon mal gesehen.
Jedes von ihnen, jede von ihnen definierte Klasse exportiert alle Operationen,
die sie als Public definieren und kann darüber hinaus auf alle Operationen zugreifen,
die in der Klasse Object definiert sind.
Und das ist unter anderem die Operation Equals. Das heißt,
ich kann einem Objekt die Frage stellen, ob es einem anderen Objekt gleich ist.
Die Standard-Implementation für Equals, das ist das, was da jetzt steht,
ist nicht die Frage, Und er beantwortet nicht die Frage,
ob ein Objekt einem anderen gleicht, sondern ob ein Objekt dasselbe Objekt ist,
wie das, was man als Parameter übergeben hat.
Das ist jetzt einfach eine Standard-Implementation, die für den Hausgebrauch
ziemlich unpraktisch ist. Weil ich möchte eigentlich ein Objekt,
das ich frage, gleichst du jemandem anderen,
möchte ich nicht, also nur dann Ja sagen,
hören,
wenn es dasselbe Objekt ist,
sondern ich möchte wirklich
zwei verschiedene gleichartige Objekte dahingehend vergleichen
Ob sie gleich sind oder ob sie ungleich sind. Deswegen müssen sie,
wenn sie also Objekte in einen,
zum Beispiel in einer Menge verarbeiten wollen,
sind sie gut beraten und auch zu anderen Zwecken,
wenn sie die Operation Equals für ihre selbstgeschriebenen Klassen jeweils neu implementieren,
und zwar so, dass ihre Klassen eine sinnvolle Vergleichsoperation implementieren.
Also, zwei Konten zum Beispiel, die sind dann verschieden,
wenn die, sagen wir mal, Kontonummer unterschiedlich ist.
Das könnte eine Vergleichsoperation für Konten sagen.
Zwei Konten sind gleich, wenn sie dieselbe Kontonummer haben.
Das ist so die Art von Vergleichsoperationen, die sie implementieren müssen.
Und dann kann also so eine vordefinierte Klasse wie der Set,
auch also den Test auf Gleichheit, in dem Sinne durchführen,
indem sie das erwarten.
So, sie sind also aufgefordert, die Operationen Equals jeweils zu redefinieren.
Und das ist ganz einfach. Man schreibt einfach in die Klasse,
die man schreibt, eine eigene Definition von Equals
hinein und schon wird diese Operation standardmäßig dann auch aufgerufen,
wenn Equals aufgerufen wird.
So, zum Abschluss noch, wie sieht das Interface List wiederum nur ein kleiner Ausschnitt?
Wie sieht das Interface für List aus? So,
ich kann erstmal diese, die sind hier unterschlagen,
alle Operationen, wie sie im Set ausgeführt werden können
Zusätzlich gibt es noch die, die für Listen typischen Index basierten Operationen.
Will heißen, ich bekomme also ein Objekt des Elementtyps,
der an einer bestimmten Stelle steht, nämlich an dem Index.
Ich bekomme, was könnten wir noch als Beispiel,
ich kann ein bestimmtes Element an der Stelle Index hinzufügen.
Ich kann ein Element der Stelle Index wegnehmen. Jetzt kommen
diese weitere Operation, was ist der Index des Objektes,
das hier als Parameter übergeben worden
Ist und das ist eine Reihe von so, sagen wir mal,
gezuckerten Operationen, die einem einfach viel lästige Programmierarbeit wegnehmen.
Da gibt es eine ganze Reihe von vordefinierten Operationen,
die dieses Interface vorsieht und die alle implementierenden Klassen natürlich vorimplementieren.
Auch ein Hirnbeispiel, müssen wir eben gucken, at at at,
hier ist es als Void definiert, das heißt,
hier gibt es mindestens keinen Clash mit dieser Art von Benutzung oder jedenfalls keinen offensichtlichen.
Was wird hier als implementierende Klasse für die Liste verwendet?
Das ist, in diesem Fall ist es die Linked-List,
so sei es drum. Was ist die Listenlänge am Anfang? Null,
ist auch klar, dann werden 1, 2, 3,
4, 5. Hinzugefügt, da Duplikate erlaubt sind, wunderbar,
ist die erwartungsgemäße Antwort für die Frage nach der Größe, ist dann 5.
Hier wird ein Element, nämlich am Index,
an der Indexstelle 1,
wird hinzugefügt
Der ganze Rest wird, ist dann über ein Index-Element höher gezählt, weiter verfügbar.
Und hier sieht man jetzt so eine etwas aufwändigere Form der Liste.
Also zunächst wird natürlich ausgeführt Aufsichtsliste, Last Index of Peter.
Oh Gott, ach Gott, das ist dann 0-1, 2, 3.
Darum kriegt man das Ergebnis 3 und dann wird dieses Ergebnis genommen,
um an der Stelle 3 ein Element zu entfernen und danach
ist hoffentlich die Liste mit der Länge gleich 4. So,
einen Bezug noch zu Ah ja, Vorlesungen,
die jetzt schon ein paar Wochen zurückliegt.
Wir haben verschiedene Arten von Schleifen kennengelernt,
unter anderem auch die Vorschleife, die vor Each Loop.
Und jetzt haben sie Collections, Sammlungen kennengelernt. Und jetzt gibt es
eine ganz spezifische Vorschleife, die genau für die Verwendung von,
oder das Iterieren über Collections definiert ist, die zumindest ganz einfach hinschreiben kann.
Sie sehen, diese Konstruktion hier, also die Vorschleife,
als Parameter eine Liste übergeben bekommt,
dass die Personenliste ist eine Liste von Personen mit,
dass jetzt diese Personenliste und ich kann jetzt mit der Vorschleife über jedes Element dieser Liste iterieren und etwas damit tun.
Das ist jetzt einfach eine etwas kürzere, angepasstere Schreibweise,
sodass also die zwei Seiten einer Medaille,
ich habe einmal die Collection, über die man iterieren kann,
die elementweise und ich habe die Vorschleife auf der anderen Seite und diese beiden Konstrukte sind einfach hier in dieser Art und Weise gut miteinander handhabbar.
So, hier kriegen Sie jetzt noch eine kleine pragmatische,
einen kleinen pragmatischen Hinweis, wann welche Art von Vorschleifen beziehungsweise Wildschleifen,
wann diese Arten von Schleifen verwendet werden sollen,
einfach um die Lesbarkeit ihrer Programme für Sie und andere zu erhöhen.
So, ich bin jetzt soweit auch durch.
Jetzt kommt die wiederum die andere Seite der Medaille
Fred wird ihnen jetzt, also den Umgang mit Sammlungen auf Java-Seite nahe bringen.
Und jetzt am Ende meines Teils der zehnten Vorlesung darf ich
Ihnen schon ein frohes Fest und einen guten Rutsch wünschen.
Und ich freue mich darauf, Sie Anfang Januar hier wieder zu sehen.
Und tschüss. Gut, ich weiß nicht,
vielleicht werde ich hier heute noch zum Mac-Fanatiker konvertiert.
Mal gucken. Ja, ich hatte also gestern die
grandiose Idee, Java 8 auf meinem Laptop zu installieren.
Und der Batteriestatus war schon rot,
aber da stand eine Stunde,
hält er noch,
hatte ich wunderbar
Lass ich die Installation laufen und mittendrin schaltet sich der Rechner ab.
Das war irgendwie nicht so schön. Danach ging irgendwie auf Paketebene
gar nichts mehr. Da hatte ich auch schon ein neues
Betriebssystem drauf, kein Problem. Und jetzt kriege ich nicht
das Bild gleichzeitig auf den Beamer und auf den Rechner.
Das ist immer wieder schön. Welche Probleme man so hat. Okay,
nichtsdestotrotz werde ich mich jetzt hier mit Guidos Mac vergnügen.
Umgang mit Listen. Also, wie fangen wir da mal an?
Wie steigen wir ein? Ihr hattet letzte Woche,
ich war ja leider nicht in der Uni,
aber ihr habt ein Projekt kennengelernt im Zusammenhang mit diesen Interfaces,
wo ist dieses Interface, Dateiverarbeiter gab.
Das können wir uns noch mal ganz kurz anschauen
So sah es aus. Ein ganz einfaches Interface,
was meine einzige Operation anbietet, namens verarbeite.
Und man steckt ein Pfeil rein.
Okay, ein Dateiverarbeiter verarbeitet also Dateien in einer Verarbeitemethode.
Sehr schön. Gut, dann gab es einen Krilienten dieses Interfaces,
der Verzeichniswanderer, der war schon vorgegeben.
Wir können uns trotzdem mal ganz kurz angucken,
so als kleinen Einstieg. Was hat er eigentlich gemacht?
Was ist der Zustand eines Verzeichniswanderers? Er weiß also,
in welchem Verzeichnis soll er anfangen zu wandern?
Das ist meistens irgendwie das aktuelle Verzeichnis oder das Home-Verzeichnis
oder kann theoretisch jedes beliebige Verzeichnis sein.
Und er kennt eben einen Dateiverarbeiter, damit er weiß,
was soll ich denn mit jeder einzelnen Datei machen,
die ich so finde im Dateisystem
Und ihr seht hier zum Beispiel, das sorgt also zum Beispiel dafür,
dieser String, dass im aktuellen Verzeihnis angefangen wird.
Wenn ihr stattdessen das Home-Verzeichnis haben wollt, dann nehmt ihr,
glaube ich, user.ho. Könnt ihr beliebig anpassen. Okay,
und der eigentliche Algorithmus zum Untersuchen, vielleicht habt ihr
euch das noch nie angeguckt. Ist auch ganz schön,
man lässt sich also alle Dateien vor zum Umverzeichnis auflisten,
in seltenen Fällen funktioniert das nicht, das muss ja abgefangen werden.
Dann geht man mit der erweiterten Vorschlafe,
die ihr heute kennengelernt habt, geht man da so durch.
Toll. Was diese komischen Klammern bedeuten,
lernt ihr leider erst nächstes Jahr kennen.
Aber ihr könnt euch das auch wie so eine Art Sammlung vorstellen.
Ja, alle Dateien liegen in so einer Sammlung,
alle Dateien von einem Verzeichnis und ich möchte mir jetzt
jede einzelne Datei nacheinander angucken
Okay, das ist also die Sammlung,
die ich mir angucken will. Unter diesen Namen möchte ich
das aktuelle Element ansprechen können und was ist der Elementtyp,
der ist Pfeil, weil es eine Sammlung von Files ist.
Okay, dann wird noch noch weitere Sicherheitsüberprüfungen gemacht,
dass man das überhaupt lesen darf, das Pfeil.
Und dann passiert was Spannendes. Es wird also geguckt,
ob es sich um ein Verzeichnis handelt und wenn es sich
um ein Verzeichnis handelt, wird die Untersuchemethode aufgerufen.
Wo ist denn die Untersuchemethode? Ha, da bin ich
ja gerade drin. Das ist also ein sehr schönes,
sinnvolles, einfaches Beispiel für Rekrusion.
Das ist so ein Das Heilsystem ist ja rekrusiv aufgebaut und
das Abarbeiten von so einem Verzeichnis ist dann genauso rekrusiv.
Ich arbeite alle Dateien ab und wenn es ein Verzeichnis ist,
dann untersuche das rekrusiv. Und hier seht ihr jetzt,
wie die Operation aus diesem Interface aufgerufen wird.
Der Verzeihungswanderer hat keine Ahnung, was da passiert.
Er kennt ja nur die Schnittstelle und weiß, alles klar,
ich kann diese Verarbeiteroperation aufrufen und einen Pfeil reinstecken.
Was da passieren wird, ist mir völlig egal.
Interessiert mich nicht. Separation auf Kunst 1. Okay. Und ja,
jetzt gab es da letzte Woche ganz viele Implementationen von diesem Dateiverarbeiter.
Einer hat irgendwie etwas in Kurzschreibweise auf die Konsole geschrieben,
eine hat etwas in langen Schreibweise auf die Konsole geschrieben.
Und jetzt haben wir hier eine andere Klasse,
die dieses Interface implementiert,
die etwas anderes machen soll
Was soll denn hier so passieren? Ah, das ist ja spannend.
Das ist jetzt also der Einstieg in die heutige Vorlesung.
Diese klasse Dateiliste soll eine Liste von Dateien verwalten.
Der Name ist vielleicht ganz sprechend gewählt. Ich sage also an dieser Stelle,
ich brauche ein Exemplarvariable von Typ List of Pile.
Ich weiß gar nicht, ob das jetzt so konkret in der Vorlesung gesagt wurde.
Also das, was man in die spitzen Klammern schreibt,
hinterlist, ist der Elementtyp der Liste.
Also wenn ich irgendwie Dateien reinsprechen will,
dann schreibe ich in die Spitzenklammern Pile.
Und wenn ich Strings reinspeichern will, schreibe ich String da rein.
Oder wenn ich irgendwie Buliens abspeichern will,
schreibe ich da Bulien rein oder so.
Gut, und dann haben wir hier so ein paar Operationen,
wo noch die Implementation fehlt.
Und ich dachte, das können wir doch einfach mal zusammen machen.
Das ist eine ganz nette Übung,
so ein erster Einstieg in den Umgang mit Listen.
Okay, ich würde mal vorschlagen, dass wir mal hier anfangen,
weil dann ein ganz interessanter Effekt auftritt.
Also, diese Methode wird jedes Mal vom Verzeichniswanderer aufgerufen,
wenn er eine Datei im Dateisystem gefunden hat.
Okay. Und was soll ich jetzt tun mit dieser Datei?
Naja, es steht ja hier im Kommentar,
fügt die übergebene Datei zur Dateiliste hinzu.
So, jetzt muss man also wissen, wie funktioniert das?
Ich habe eine Liste, ich habe ein Element und
ich will jetzt dieses Element in die Liste reintun.
Hat jemand einen Vorschlag, wie ich jetzt diese Datei in
die Liste reinbekomme
Ja. Ja, genau, du hast gesagt,
ich muss also erst mal, um welche Sammlung handelt es sich,
die kommt als erstes, jetzt möchte ich mit der Sammlung reden,
schreibe ich den Punkt hin,
dann schreibe ich Ed und dann schreibe ich hin,
welche Datei das sein soll.
Also das Tippgefühl ist nicht schlecht auf dem Mac im Tausch, gefällt mir. Gut,
wenn man sich nicht daran erinnert, dass dieser Befehl Ed heißt,
dann gibt es etwas, ich weiß gar nicht,
ob das in dieser uralt Bluejoy-Version schon drin ist.
Ah ja, genau. Also wenn ihr Steuerung,
Leertaste drückt, den Shortcut kennt ihr auch schon von Carol,
dann wird hier quasi die gesamte Schnittstelle so schön interaktiv aufgelistet.
Dann könnt ihr sehen, was kann man denn alles
so damit machen
Okay, wir haben Glück. Dadurch, dass das
mit A anfängt, haben wir sofort einen Treffer gelandet.
Also offenbar ist es diese Operation. Aber man kann es sich
mal hier schön drüber angucken, was gibt es denn da alles?
Ich kann auch ganze Collections da reintun. Clear hatten wir
in der Vorlesung, ich kann fragen, ob was drin ist.
Toll. Also ihr müsst gar nicht irgendwie extra den Internet-Explorer
aufmachen oder den Firefox und irgendwie googeln,
was gibt es denn auf so einer Liste in Java?
Ihr nehmt einfach den Punkt, sagt Steuerung,
leertast und dann seht ihr wunderbar, was kann man denn so alles damit machen.
Gut, also ich füge es jetzt mal hinzu.
So, wups. Und das möchte ich jetzt einmal ausprobieren.
Das wird nicht funktionieren, aber ich will das einmal,
dass ihr das seht, dass es nicht funktioniert.
So, wie benutze ich das denn jetzt?
Ich mache einmal mehr diesen Verzeichnishandlerer
Okay, dann mache ich mir diese Dateiliste. So,
und jetzt sage ich die Verzeihungswanderer,
starte doch mal und ich übergebe dir jetzt einen Dateiverarbeiter,
wenn du weißt, was du mit den einzelnen Dateien machen sollst.
Und der Dateiverarbeiter ist ja hier diese Dateiliste. So,
und jetzt wird es, Achtung, wird es gleich knallen.
Hm, Java Lang, Nowled Porter Exception, Now.
Das ist ja komisch. Hat ja mal eine Idee,
warum jetzt dieser Fehler hier aufgetreten ist.
Genau, wir haben gar keine Liste. Es sieht immer so,
verführerisch auszudenken, naja, der Typ von Dateien ist ja Liste,
also habe ich doch sicherlich irgendwie eine Liste in der Hand,
habe ich aber nicht,
denn ihr müsst euch wieder klar machen,
es handelt sich ja hier um eine Referenzmaria ab,
ich habe so einen kleinen Kasten im Speicher,
wo eine Referenz drin gespeichert ist und in diesem Fall ist Sardinialreferenz drin,
der Standardwert für Referenzvariablen ist ja nahe.
Also durch diese Zeile wird keine Liste im Speicher angelegt,
es wird nur gesagt, diese Variable Unterstrichdateien kann auf Listen verweisen.
Gut, wir müssen also irgendwie eine Liste erzeugen,
wie mache ich das denn
Ja, wen hatte ich denn mal in langer Zeit nicht?
Ich. Du sagst, New Olist, ich mache mal so vielleicht.
Da denken wir mal fünf Sekunden drüber nach, ob das funktionieren kann.
Wir drücken auf Compiled. Java, Utilist is abstract.
Can out be a instanciated. List ist ja ein Interface
, ne? Ja. Man muss, ich glaube,
die wurde Array eingebunden. Array ist sehr schön,
ne? Array List ist also eine Klasse,
die dieses Interface List auf eine mögliche Art und Weise implementiert.
Sehr schön. Und nur von Klassen kann ich ja
Exemplare erzeugen, mit diesem New Operator.
Okay, das wird jetzt funktionieren,
das probiere ich nicht aus, das raubt bloß halt.
Bis jetzt sieht man ja noch gar nichts Spannendes.
Und jetzt könnte man mal was Spannendes sehen.
Wir ignorieren mal ganz kurz diesen Kommentar. Letzten Endes wollen
wir, dass irgendwelche Zahlen noch vor den Dateinamen stehen.
Ich will jetzt erstmal einfach nur ganz stumpf die Dateinamen auf die Konsole schreiben.
Mehr will ich gar nicht. Habt ihr das schon mal gehört?
Ich habe also eine Liste mit ganz, ganz vielen Elementen
und ich will jetzt für jedes Element der Liste etwas tun.
Kam das heute dran in der Vorlesung?
Genau, die Fortschlaf. Und wie ging die nochmal?
Ich schreibe sie einmal abstrakt hin. Ja,
dass ihr wisst, wo schreibe ich jetzt was rein?
Also was muss als erstes stehen, der Element-Typ?
Der steht immer als erstes, ja. Dann steht ein
beliebiger Name. Ich schreibe das mal ruhig so hinter,
so, ich weiß, hier könnt ihr euch einen ausdenken.
Dann kommt ein Doppelpunkt und dann kommt die Sammlung, über die wir iterieren wollen.
Sammlung. Und dann kommt der Rumpftisch live. Ach so,
nee, geschweifte Klammer auf, hatte mir Guido verraten,
war, ach, jetzt habe ich es schon wieder vergessen.
Irgendwas mit einer Acht. Ah, hier haben wir es, alt,
acht, alles klar. Dann ist es sicherlich alt,
neun zum Schließen, funktioniert auch. Ja. So,
und ich finde es am am einfachsten, rechts anzuzufangen.
Wie heißt denn die Sammlung oder wie heißt die Variable,
wo die Referenz auf die Sammlung gespeichert ist,
über die
wir iterieren wollen
Ja. Genau. Über diese Liste wollen wir icherieren.
Gut. Was ist denn der Element-Typ der Liste?
Sind da Strings drin oder Zahlen oder Konten?
Ja. Genau. Sehr schön. Und was ist jetzt
die korrekte Antwort für den beliebigen Namen?
Naja, irgendwas Sprechendes, sagen wir mal, vielleicht Datei.
Das klingt doch ganz gut. Ihr könntet aber genauso gut
X oder Fu oder irgendwas nehmen. Ist völlig egal. So,
und jetzt kann ich im Rumpf der Schleife mit diesem Datei
machen, was ich will,
zum Beispiel
auf die Konsole schreiben
System out, Printline, Datei. Das heißt also,
wenn dieser Rumpf das erste Mal betreten wird,
dann ist Datei eine Referenz auf das erste Objekt in der Sammlung.
Und wenn er das zweite Mal betreten wird,
eine Referenz auf das zweite Objekt in der Sammlung und so weiter.
Jedes Mal, wenn der Rumpf betreten wird, zeigt Referenz
dann immer so nach und nach auf das nächste Element.
Gut. Ach, das können wir doch mal ausprobieren.
Ich weiß gar nicht, was es bedeutet,
eine Datei auf die Konsole zu schreiben.
Möglicherweise kommt da der ganze Pfad und so.
Das ist mir jetzt gar nicht so wichtig. Ich wollte euch
einfach mal nur zeigen, wie die Vorschleife so aussieht.
Sodass es noch von vorher, kann ich hier irgendwie einstellen,
Peer Screen and Method Talk, sonst wundere ich mich immer,
wie alt diese Fehlermeldungen sind
Gut. Also, neues Spiel, Verzeichniswanderer erzeugen. Und da teilliste erzeugen,
dem Verzeichniswanderer sagen, wandere doch mal und stopft doch mal
die ganzen Dateien hier rein in diese Liste.
Das möchte ich, dass du das tust.
Und jetzt sind die alle drin in dieser Liste.
Und ich kann doch jetzt mal sagen, schreibe auf die Konsole.
Ah. Okay, das schließe ich jetzt mal wieder ganz schnell.
Das geht uns ja nicht an, was da alles drin ist.
Gut, sehr schön, hat funktioniert. Okay,
ist noch was anderes Spannendes, was wir hier machen können?
Lösche. Wie löscht man denn
Alle Einträge in so einer Liste, schauen wir mal,
Steuerung, Leertaste ist hier irgendwas,
was mit Löschen zu tun haben könnte.
Ah, hier. Sehr gut, machen wir das.
Und das könnt ihr vielleicht in eine Übung selber machen.
Aber hier haben wir jetzt mal einige interessante Eigenschaften gesehen von
solchen Sammlungen. Also, wenn ihr solche Variablen deklariert,
dann nehmt ihr meistens so einen Interface-Typ wie List oder Set.
Ihr könnt ja sogar Collection an dieser Stelle nehmen, das ist noch genereller.
Und bei der Erzeugung entscheidet ihr euch dann nun für zum Beispiel Air-Ray-List.
Es gibt aber auch Linklist und noch so ein paar andere.
Ich nehme immer die Air-Realist, ich habe einfach keine Lust,
darüber nachzudenken,
um eine andere sinnvoller wäre
Genau, so fügt man ein Element zur Analyste hinzu.
Und so kann ich schön über alle Elemente der Sammlung rüber iterieren.
Gut, ich will vielen auch einmal zeigen,
wie man früher über Sammlung rüber iteriert ist,
bevor es diese schöne For-Each-Schleife gab.
Da hat man sich einfach überlegt, naja,
in der Liste haben ja die Elemente einen Index.
Dann kann ich doch einfach über die Position einfach drüber iterieren.
0, 1, 2, 3, 4,
5 und ich sage dann jeweils in der Sammlung,
geh mir darum, hat das Element an der Stelle null.
Gib mir doch mal das Invent an der Stelle 1
und so weiter. Da könnte ich also einfach schreiben,
ich fange bei null an.
Wie lange muss ich den jetzt iterieren? Weiß ich noch nicht
genau. Und ich will ihn immer um einen erhöhen.
Ach, nee, die geschweifte Klammer auf.
So. Zu. Vor, in das Boot. Das ist
in diesem Fall völlig egal, ob ich plus,
bis oder i plus, plus hatte.
Wir hatten in einer Vorlesung mal fünf Minuten darüber diskutiert,
was man hier nimmt und es ist völlig egal.
Genau. Also, ja, hm, was wäre denn jetzt eine sinnvolle Schleifenbedingung?
Also wenn ich zum Beispiel zehn Elemente habe,
dann würde ich hier sicherlich stehen i-Klammer 10, oder?
Oder müsste das den i-Klammer gleich zählen? Ich glaube,
i-Klammer 10 ist richtig. Aber diese zehn, naja,
ich will ja hier nicht die zehn hinschreiben,
sondern die Größe dieser Liste, wie viele Elemente da drin sind,
Es könnte länger oder es könnte size sein, ich verwechsel das auch immer.
Schauen wir mal ganz kurz. Wir fragen einfach auf der Liste,
hey, was bietest du denn so alles an?
Gibt es hier so was wie Langs? Nee,
längs gibt es nicht, dann ist es wahrscheinlich size.
Ja, genau, da haben wir es. Toll. So,
wir können uns einmal ganz kurz versichern, dass das funktioniert.
Also nehmen wir mal an, die Liste ist leer.
Dann will ich ja irgendwie gar nicht in diesen Schlafen rumfragen gehen.
Dann würde ich hier null zurückkommen und ich würde die Frage stellen,
ganz am Anfang ist null kleiner als null.
Nein, ist es nicht, dann würde ich
den Schlafen rum überspringen und hier weitermachen. Gut,
wenn ein Element drin ist, würde ich sagen,
ist null kleiner als eins,
ja,
würde mit dem Wert null
hier reingehen
Dann wird es auf eins erhöht. Ich frage, ist eins,
kleiner 1-1, nein, würde ich rausgehen.
Also das stückt, ja. Es wird genau die richtige Anzahl
von Schleifendurchlaufen gemacht. Gut. Jetzt müssen wir mal gucken,
wie komme ich denn jetzt an das Element an einem bestimmten Index ran?
Wie kann ich dieser Liste sagen? Ich interessiere mich für
das Element Nummer I. Irgendjemand anders nochmal.
Ja. Hört der Methode Geld, ne? Also,
ist hier was mit Guette, damals, genau,
an der Stelle I. Ich glaube, das war ich dann
, Klammer
Genau, das geht also genauso und jetzt kann ich eben auch den Vorteil,
ist halt, ich kann jetzt davor noch diesen Index ausgeben,
ja, ich könnte jetzt also schreiben, alles klar,
ich will erst den Index ausgeben,
dann soll ein Punkt und eine Lehrtaste kommen und dann soll erst das eigentliche kommen,
ja.
Diese Möglichkeit, mit dem Index noch zu spielen,
gibt es eben nicht bei der erweiterten Vorschleifung.
Ja. Meiner Vorschleifung, wo ich leite, kann man
allererstes trotzdem, so gemütlicher das fahren, die wechselnde Glaubensreise.
Du hast recht, man könnte manuell einen Index mitlaufen lassen.
Ich könnte also sagen, I soll bei null anfangen und
ich möchte jedes Mal am Ende I um einen erhöhen,
dann hätte ich auch wieder einen Index.
Klar, könnte man genauso machen
Anstatt umgeht, wird in eurer Gegend glauben. Leider nein
. Es gibt keine Möglichkeit, in Java zu sagen,
ich möchte Operatoren, die für andere Typen Sinn machen,
auch für eigene Klassen, dass die da Sinn machen.
Das geht nicht. Leider nicht. Bei RS geht das
, aber nicht bei Listen. Ja. Genau.
Sehr schön. Das also als kleiner Einstieg in Listen.
Okay. Also die Uhr sagt, es ist 25,
was stimmt jetzt? Ich habe jetzt hier fünf Uhren und
alle zeigen was anderes an.
Okay. Mal schauen
Also so, dazu werden wir wahrscheinlich keine Zeit mehr haben.
TikTok, Kunde, wo ist denn das Blu-ray-Fenster?
Wie komme ich denn beim Mac? Ah, hier sind
ganz viele Blu-ray-Fenster. Tja, welcher wird das jetzt sein?
Ich probiere einfach mal, nee. Achso,
das... Wie komme ich an Fenster,
die ich minimiert habe auf dem Mac?
Hier vielleicht. Gebt Geburtstag, ah hier, ah,
sehr gut, das wollte ich.
Gut. Okay, das ist also ein Projekt,
was noch nicht übersetzbar ist
Weil da noch etwas fehlt. Es fehlt einfach noch eine Implementation zu
diesem Interface. Okay. Aber was ganz spannend ist,
ist diese Klasse Tag, kann ich die nicht zumindest übersetzen?
Ja, die kann ich übersetzen, sehr gut.
Was ist so ein Tag? Das schauen wir uns auch mal
ganz kurz an. Also, diese Klasse Tag sagt,
ich möchte über einen Tag in einem Jahr reden,
aber das Jahr ist mir egal.
Also ich will sowas ausdrücken wie 1. April oder irgendwie 5.
August oder 24. Dezember oder so.
Eine Klasse, die irgendwie so einen Tag im Jahr modelliert.
Und das ist ganz einfach gelöst. Die hat einfach intern
einfach nur einen Int und dieser Int könnte irgendeinen Wert annehmen
zwischen 0 und
65, ne? Dann hätte ich 366 verschiedene Tage,
dann sind Schaltjahre auch mit abgefrühstückt.
Sehr schön. Okay. Und so, ja,
kann ich das auch konstruieren, so ein Abjekt.
Ich liefere einfach so eine Nummer rein, die darf nicht
kleiner sein als null und ich größer gleich diese 30066 wahrscheinlich.
Sonst gibt es eine Acception. Gut. Also ein ganz einfaches Objekt,
was einfach nur eine Zahl speichert zwischen null und 365.
Okay, auch das True String ist jetzt, glaube ich,
nicht so spannend. Da kann man sich hier noch
einen zufälligen Tag geben lassen. Da wird noch berücksichtigt,
dass der 29. Februar weniger wahrscheinlich sein darf, als die anderen Tage.
Mein Gott, das ist jetzt auch nicht so spannend.
Okay, und das hier alles ist nur,
damit man das irgendwie schön sichtbar sieht.
Ich habe also einfach ein Objekt, was einfach nur Intention inspannen.
Okay, und damit möchte ich jetzt mal so
ein bisschen spielen
Also, Direkteingabe. Wie kriege ich jetzt hier meine Direkteingabe?
Show, Codepad. Ah, hier habe ich es.
Ich kann es hoffentlich größer ziehen. Ja, genau,
sehr gut. Also, ich mache mir mal so einen Tag,
ja? Ich bin jetzt nicht besonders gut im Kopfrechnen.
Ich nehme jetzt mal den Nulten. Das ist ja dann
der allererste Tag, den es gibt.
Das ist quasi der 1. Januar. Und jetzt habe ich
diese Objektreferenz, die speichere ich mir mal. Ach ja,
ach, ich nenne es mal A. So. Gut,
machen wir noch einen neuen Tag.
Nochmal den 1. Januar und speichern mir das wieder.
Als, sagen wir mal,
B. Okay
Jetzt habe ich hier also zwei Referenzen. Die eine heißt A,
die andere heißt B. Diese Referenz verweist auf dieses Objekt und
diese Referenz verweist auf dieses kann ich die gleichzeitig sehen.
Also ihr glaubt mir, dass es verschiedene Objekte sind,
weil sie an verschiedenen Stellen, schade,
auf meinem Rechner sind die immer gleichzeitig sichtbar.
Na gut. Okay, ich kann jetzt mal hier so ein paar Abfragen machen.
Also ich kann zum Beispiel fragen, ist A, gleich,
gleich B. Was vergleicht der Gleichgleichoperator oder Vergleich der Referenzen?
Da würde er so schauen, Zeit A auf dasselbe Objekt wie B.
Also dann würde es True zurückgeben und in allen anderen Fällen
würde er Vollzeit geben. Und da ist ja zwei,
da ist ja zwei Objekte sind und nicht eins,
kommt da auf jeden Fall
Fall Source
Während wenn ich zum Beispiel schaue, ob A, auf dasselbe Zeit VR,
dann ist das natürlich identisch und da kommt True raus.
Okay. Was ist jetzt aber,
wenn ich sagen will, es interessiert mich gar nicht,
ob es dasselbe Objekt ist, sondern es interessiert mich,
was steht denn hier für ein Int in diesem Objekt und was steht denn hier in diesem Objekt?
Also wenn ich zum Beispiel hier ein Objekt habe für den
1. Januar und hier ein Objekt für den 1. Januar,
da würde ich gerne irgendeine Art von Test haben,
die mir sagt, dass es gleich ist.
Und jetzt hatte Guido ja schon über die E-Quiz-Operation geredet,
wenn ich das schon sage, A,
E-Quiz B und ich habe sonst nichts weiter unternommen,
dann wird er leider blöderweise auch False rauskommen.
Weil ich in der Klasse Tag eben noch ganz schnell
dieses Equals rausgelöscht hatte
Also es gibt ja nirgendwo diese Equels-Operation. Die wird also einfach,
ja, von der, von der Klasse Object einfach dann verwendet.
Dann schreiben wir doch mal unsere eigene Equels-Operation. Wo schreibe
ich sie mal hin? Vielleicht hier. Gut. Also
wie sah die aus? Sie liefert einen Bulien zurück.
Sie soll ja die Frage beantworten, ob es so ist
oder nicht. Ich habe es. Sie heißt Equels.
Und jetzt gibt es schon so den ersten Stolperstand.
Man könnte jetzt vielleicht denken, dass man hier Tag reinschreibt.
Das wird in manchen Fällen, wird es das tun,
was man will, in anderen wieder nicht.
Man muss wirklich diese Signatur hinschreiben,
dass man sagt,
da wird ein Objekt reingesteckt
Weil Java eben so definiert ist, dass es sagt,
es muss die Möglichkeit geben,
jedes Objekt mit jedem anderen Objekt zu vergleichen.
Also der Programmierer muss die Frage stellen dürfen,
ist dieser Tag gleich mit diesem Konto zum Beispiel?
Oder ist dieser Benutzer gleich mit diesem String?
Ziemlich sinnlose Frage, weil man muss die stellen dürfen.
So ist Java halt definiert und C-Sharp ist zum Beispiel genauso definiert.
Okay, das ist jetzt ja irgendwie komisch. Wie wollen
wir denn jetzt diesen Vergleich machen? Also ich weiß ja,
dass der Benutzer das auf jeden Fall auf einem Tagobjekt aufgerufen hat.
Ich bin ja hier in der Klasse Tag. Okay,
ich kann also hier auf dieses Tagnummer von mir selber einfach zugreifen.
Aber jetzt bei diesem Objekt kann ich das nicht
Gegenge könnt ihr euch einfach schreiben, okay,
alles klar, ich gucke einfach,
ob die Tagnummer gleich ist mit der Tagnummer des Objekts oder so.
Das wird nicht funktionieren. Warum wird das nicht funktionieren?
Der Compiler schaut sich diesen Typ an, Object,
der ist ja schon irgendwie 20 Jahre alt oder so und schaut,
gibt es denn da irgendwie eine zugreifbare Exemplarvaria-Pilanz unter Strich-Tagnummern?
Das macht der Compiler. Schon,
wenn ich jetzt hier drücke und würde sagen,
tut mir leid, davon habe ich noch nie was gehört.
Tatnummer gibt es bei Objekten nicht. Hier könnte ja jedes beliebige Objekt angucken,
das könnte ein Kunde sein, ein Konto und String,
die haben ja alle gar nicht solche Tagnummern.
Deswegen lässt der Compiler das nicht zu und einer statisch getypten Programmiersprache.
Gut, dieser einfache Ansatz wird also leider
nicht funktionieren
Ich muss erst mal schauen,
was hat mir denn der Benutzer da eigentlich reingesteckt?
Was ist es denn für ein Objekt? Ist es ein Kunde,
ist es ein Tag, ist es ein Konto?
Und dafür gibt es einen ganz speziellen Operator in Java.
Das schreibt man dann so. So, was passiert hier
? Also hier steht erst mal irgendeine Referenz, okay?
Und jetzt prüft also dieser Operator, ich schaue mal,
auf was für ein Objekt diese Referenz verweist und von welcher Klasse dieses Objekt ist.
Ich schaue, ob es von der Klasse Tag ist.
Und wenn es von der Klasse Tag ist,
dann werde ich in diesem Rumpf
drin landen
Ansonsten kann ich eigentlich direkt, kann ich eigentlich direkt Fords zurückgeben.
Hups. Also dieses Return Falls ist deswegen sinnvoll,
weil ich sage, wenn jemand die Frage stellt,
ob dieser Tag gleich ist, mit diesem Nicht-Tag,
dann kann das sicherlich nur Fouls sein.
Gut. Wenn es jetzt ein Tag ist,
könnte man vermuten, dass ich vielleicht jetzt sowas schreiben kann,
wie alles klar, ist denn die Tagnummer gleich mit Objekt.tagnummer.
Ich habe mich jetzt ja davon überzeugt,
dass es ein Tag Objekt auf jeden Fall ist,
dann müsst ihr euch doch eigentlich darauf zugreifen können.
Schauen wir mal. Nee,
funktioniert auch nicht
Was ist denn der statische Typ der Variablen? Obj. Welchen
statischen Typ hat diese Variable? Ja. Object, genau.
Und der statische Typ einer Variable ändert sich ja nie.
Das heißt, für den Compiler ist an dieser Stelle immer
noch völlig klar, es handelt sich um ein Objekt.
Ich weiß nicht, um was für ein Objekt es sich handelt.
Der ist nicht schlau genug zu verstehen,
dass er zwei Schritte vorher ja gerade geprüft hat,
ob es ein Tag ist. Und nach dem Motto,
wenn ich dann in dem Block lande,
dann müsste ich ja eigentlich alles mit dem Optisch machen dürfen,
was man mit Tagen machen kann.
Aber so ist Java leider nicht definiert. Es gibt neuere,
modernere Programmiersprachen, die den Begriff statischen Typen ein bisschen anders definieren und sagen,
alles klar,
innerhalb dieses Blocks ist es dann ein speziellerer Typ,
das ist in Java
nicht so
Wir haben jetzt also eine interessante Situation. Bevor wir dieses IF ausgeführt haben,
ja, hatten wir eine Referenzvariable vom statischen Typ Object.
Die hat auf ein Objekt gezeigt,
wo wir nicht wussten, was der dynamische Typ ist.
Es könnte irgendein Objekt gewesen sein. Okay. Innerhalb von
diesem IF ist jetzt eine etwas andere Situation.
Wir haben immer noch eine Variable vom statischen Typ Object.
Wir wissen aber, dass der dynamische Typ Tag ist.
Sonst würden wir nicht in diesem Rumpf des IFs drin sein.
Und wir müssen jetzt irgendwie die Möglichkeit haben zu sagen,
hm, ich will jetzt eine Referenz auf dieses Objekt haben,
was denn, die den statischen Typ Tag hat,
damit ich mit dem Objekt als Tag umgehen kann.
Und das hat eine ganz, ganz merkwürdige Schreibweise, das zu sagen.
Ich sage also folgendes. Jetzt brauche ich irgendeinen Namen.
Sagen wir mal, ja, was nehmen wir denn nochmal?
Vielleicht übergebener Tag, übergebener Tag oder so. Ich mache mir
jetzt also eine zweite Variable von dem statischen Typ, den ich brauche.
Und würde jetzt ja gerne sowas schreiben wie, so.
Ich will also, nur diese Variante zeigt hierhin und ich will jetzt auf dasselbe Objekt zeigen.
Das macht man ja normalerweise mit der Zuweisung über Referenzen.
Das wird der Compiler leider auch nicht akzeptieren,
weil er einfach sagt, tut mir leid,
optisch ist immer noch, argumentiert immer noch mit dem statischen Typ,
das könnte ja schief gehen.
Und deswegen muss ich jetzt den Compiler davon überzeugen,
dass das nicht schief gehen wird.
Und das schreibt man so hin.
Ja, das ist eine ganz,
ganz merkwürdige Sundheit
Puh, okay, ich sage also an dieser Stelle,
lieber Compiler, pass auf,
der statische Typ dieses Ausdrucks ist Object,
weil die Variable nur mal den statischen Typ Object hat.
Ich möchte jetzt aber eine Referenz haben vom statischen Typ Tag.
Okay, das heißt, dieses Geld markierte,
ist jetzt eine Referenz vom statischen Typ Tag.
Und diese Referenz speichere ich mir in dieser Variablen,
die auch vom statischen Typ Tag ist.
Okay, man nennt diese Zeile einen Typ Typ Test,
man nennt diese Zeile eine Typ Zusicherung
Diese Zeile ist erforderlich, weil wir einfach nicht wissen können,
was der dynamische Typ ist.
Und diese Zeile ist erforderlich, falsche Aura eben so blöd ist.
Ja, gut. Okay, und jetzt können wir endlich
das machen, was wir eigentlich machen wollten.
Ich kann also sagen, ich möchte prüfen,
ob meine eigene Tagnummer dieselbe ist oder die gleiche bei Zahlen,
macht das ja keinen Unterschied, wie vom übergebenen Tag die Tag bauen.
Ja. Oh ja, natürlich, danke.
Das wird der Compiler mir hoffentlich auch sagen.
Cannot ist seine Value, wunderbar. Ja, ich will
ja vergleichen.
Schön. Das funktioniert, das ist doch toll.
Es ist übersetzbar. Das ist doch toll. Dann schauen wir
mal, ob ich das jetzt auch sinnvoll verwenden kann.
Also ich kann das ja auch direkt hinschreiben, oder?
Tag A ist gleich ein New-Tag. Null. Tag B
ist gleich ein New-Tag. Null. Und jetzt frage ich
diese Frage und da kommt Schuh raus.
Toll. Kommt auf das einmal hier so einen Haltepunkt setzen.
Ich liebe halt Punkte. Und ich stelle die Anfrage nochmal
. So, jetzt sind wir im Debugger
Okay, wir haben also hier diese Objektreferenz vom statischen Typ Object.
Ich klicke da einmal doppelt drauf. Das ist also das Objekt.
Man kann also hierran sehen, dass der dynamische Typ Tag ist.
Das Objekt vergisst ja niemals sein, die Klasse, von der es erzeugt wurde.
Sehr gut. Wir prüfen jetzt also quasi an dieser Stelle
, prüfen wir, ob hier Tag steht. Okay,
das prüfen wir mit dieser Zahl, mit diesem Typtest.
Das steht doch tatsächlich, also landen wir jetzt im Rumpf des Ifs.
Und jetzt wird hier eine zweite Variable angelegt werden.
Seht ihr das? Wir haben jetzt hier zwei Variablen,
die hier, das ist der Parameter,
der uns reingesteckt wurde, wo wir gar nicht genau wussten,
was für ein Objekt verbirgt sich da eigentlich hinter.
Und das ist jetzt die Variable, die wir
hier gerade angelegt haben
Die hat jetzt den spezifischen statischen Typ Tage. Ich kann jetzt also
alles damit machen, was man mit Tagen so machen kann.
Und das Interessante ist, dass es dasselbe Objekt ist.
Ich schiebe das jetzt mal nach hier.
Und wenn ich jetzt hier raufklicke, ist es das Objekt.
Also es ist wirklich dasselbe Objekt. Es wurde jetzt also
nicht irgendwie dieser Tag irgendwie kopiert oder irgendwas,
sondern es wurde einfach nur gesagt, ich brauche eine zweite Referenz,
die auf dasselbe Objekt zeigt, aber mit dem Wissen,
dass es sich um einen Tag handelt,
damit ich auf Tageigenschaften zugreifen kann.
Okay. Gut. Gibt es bis hierhin
erstmal Fragen
Ist schon komisch. Dieses Thema zu gucken,
was ist es eigentlich für ein Objekt und dann muss ich
da irgendwie so einmal mit dem Nudelholz auf das Typsystem raufhauen.
Das braucht man in dieser Equals-Methode,
ansonsten in guten Entwürfen braucht man das eigentlich fast nie.
In guten Entwürfen sagt er einfach nur, hey,
ich habe ein Objekt, ich weiß nicht genau, was es ist.
Ich rede mal mit dem Objekt und sage,
verschieb dich mal oder ändere mal deine Farbe.
Das wird schon selber wissen, wie es das zu tun hat.
Normalerweise muss man extrem selten fragen,
was ist denn jetzt eigentlich wirklich der dynamische Typ dieses Objekts?
Okay. Gut, sehr schön. Jetzt haben wir so
diese Equals-Methode überschrieben und jetzt möchte ich eigentlich als nächstes mal,
wir haben jetzt ja über Listen geredet,
ich möchte auch nochmal über euch mit mit euch über Mengen reden.
Also läuft das Programm noch wahrscheinlich mit dem Debugger.
Ich mache hier einfach mal kurz die Zuckerstange und so.
Gut, wir machen uns mal ein Hash-Set. Also,
ähm... Ach, das Set kann ich wahrscheinlich gar nicht benutzen.
Kann man hier eigentlich auch Importien schreiben? Geht das in
der Direkteingabe? Ah ja, das scheint zu funktionieren, sehr gut.
Dann mache ich mir doch mal ein neues Hash-Set von Tagen.
So, das nenne ich mal S-B-Set. Sehr gut.
Und jetzt mache ich mir wieder meine beiden Tage A und B.
Also Tag A, gleichen Ju-Tag,
Tag B, gleich nur Tag 0. Jetzt habe ich schon
wieder zwei Objekte, die für den 1. Januar stehen.
Und die würde ich jetzt mal beide hinzufügen.
Ach, das geht nur mal ziemlich cool und schade.
Ich hatte gehofft, dass jetzt die Sabulien angezeigt wird.
Na gut. Das ist ja sehr schade, weil hier
nämlich jetzt immer Ergebnis rauskommt, was euch möglicherweise wundern wird.
Was würdet ihr jetzt erwarten? Wir haben ja gesagt,
in Mengen sind ja keine Duplikate zugelassen. Wir haben jetzt definiert,
was es bedeutet, wenn zwei Tage gleich sind.
Und ich habe jetzt den 1. Januar zweimal eingefügt.
Jetzt könnte ich ja das Set fragen, wie groß bist
du eigentlich? Da gibt es jetzt mehrere Möglichkeiten.
Vielleicht hat das überhaupt nicht geklappt. Irgendwas einzugeben,
wer glaubt, dass gar nichts drin ist in dem Set
Okay. Wer glaubt, dass es ein Element drin ist?
Ja, so dutzend Leute. Wer glaubt, dass zwei
Elemente drin sind? Ja, auch nicht viel mehr.
Ja, okay, schauen wir mal.
Wie komme ich denn jetzt an die Größe?
Ich muss ich mir das erst in der Variablen ablegen.
Okay, also In-N ist gleich S.size. Wenn er das
so will, bitteschön. In zwei, Tatsache.
Er hat also, er hat nicht wirklich erkannt,
dass es Duplikate sind. Das ist komisch, oder?
Und jetzt gibt es etwas für Juristen
Es gibt einen sogenannten Vertrag. Es gibt einen Vertrag zwischen Equals und einer weiteren Methode.
Und diesen Vertrag werdet ihr möglicherweise erst in fünf Wochen verstehen.
Aber ihr müsst ihn jetzt erst mal akzeptieren.
Also, es gibt einen Vertrag, der sagt folgendes.
Ich konnte es euch hier einfach mal so hinschreiben.
Der sagt folgendes. Wenn dieser Ausdruck wahr ist,
A. Equals B, dann muss durch den Programmierer geeignet sichergestellt sein,
dass eine spezielle Operation Hashcode auf A dasselbe zurückliefert,
wie die Operation, wenn ich sie auf B aufrufe.
Was Hashcode genau ist, wie gesagt, keine Angst,
lernt ihr alles noch kennen, wenn wir über Hashing reden.
Aber ihr könnt es euch vorstellen,
wie kann man sich das
am besten vorstellen
Und es ist irgendwie eine zusammengegedampfte Zahl, die aus dem Zustand
des Objekts berechnet wird. Und es wird also gesagt,
wenn die Zustände von A und B gleich sind und ich möchte eine Zahl berechnen,
die deterministisch aus dem Zustand sich nun mal berechnet,
dann sollte hier dasselbe rauskommen wie da, ja?
Ja, so war ich das verstanden habe. Das habe ich über eine Verstützung gehört,
das mit Herrshport, einfach verschiedene Möglichkeiten und Informationswerten,
weil etwas ganz Großes und etwas Kleines, auch über zu deckeln.
Ja, der findet auf jeden Fall eine Komprimierung von Informationen statt, das ist richtig.
Ja, das ist halt, wenn man sich vorstellen kann,
das sind die Quertore, Könnte man machen, ja.
Genau. Also okay, und diese Operation Hashcode,
muss ich also immer dann auch selber implementieren,
wenn ich mein eigenes Equals angeboten habe, damit dieser Vertrag nicht verletzt wird.
Okay. Ach, jetzt die geschweiften Klammern, war so und so.
Gut. Puh. Hat ja mal eine Idee,
wie ich das erreichen kann, wenn also dieses Equals sagt,
alles klar, hier ist der 1. Januar,
hier ist der 1. Januar,
da kommt True raus oder hier ist der 24. April und hier ist der 24. April,
ich gehe mal True raus.
Dass dann das Hashcode sowohl auf A als auch auf B
aufgerufen,
jeweils dasselbe zurückliefert
Muss irgendwie aus dem Zustand des Objekts deterministisch einen Int berechnen.
Was ist denn der Zustand des Objekts? Schauen wir uns
das nochmal ganz kurz an. Das ist ja ziemlich einfach,
oder? Also ich habe einen Zustand und ich will jetzt
einen Int liefern, der sich aus dem Zustand ableiten lässt.
Ich warte nochmal, dass sich irgendjemand meldet,
der sich auch noch gar nicht gemeldet hat.
Ja. Genau, wir können einfach die Tagnummer zurückgeben.
Das ist also extrem trivial in diesem Fall.
Sehr schön. Wo bin ich denn jetzt hier,
hier?
Return, Tagnummer
Ups, nee, wie spare ich euch denn hier so?
Gut. Das probieren wir nochmal ganz kurz aus.
Also, ich mache mir ein neues Hashtag.
New Hashtag Set von Talk. Ach, ich muss
wieder importieren. Import, Jarba, YouTube, sterben.
So, jetzt ziehe ich mir das wieder hier rüber.
Ich nenne es wieder Ess, mal wie vorher.
So. Jups. So, und jetzt füge ich wieder hinzu.
So, und ups
Gut. Jetzt wird es wieder spannend. Wie viel sind denn jetzt drin?
Wer glaubt, dass jetzt nur noch eins drin ist?
Ja, gut. Wer glaubt, dass jetzt immer noch zwei drin sind?
Auf fast keiner mehr, dann schauen wir auch mal.
Toll. Sehr gut. Ja, ich kann also das
A jetzt direkt fragen, was ist denn dein Hashcode?
Wunderbar, null, weil das ist eben der Tag,
der dann gespeichert ist. Und bei B ist es genauso.
Und wenn ich mich jetzt noch vielleicht am dritten Tag erzeuge,
der irgendwie mit der Eins vielleicht initialisiert ist und ich frage jetzt hier zum Beispiel,
das ist denn der Hashcore von Cinder,
wird dann natürlich eins mal rauskommen, ja.
Genau. Und wenn ich den jetzt hinzufüge zu meinem Set
, dann wird das wunderbar funktionieren.
Und wenn da jetzt insgesamt zwei drin sein. Das B
wurde nicht hinzugefügt, weil das A ja schon drin war.
Und das C, was anders ist, konnte ich aber hinzufügen.
Ihr müsst immer höllisch aufpassen, was gerne mal passieren kann,
ist, dass man sich hier irgendwie vertippt.
Ja, der Compiler wird das nicht merken, der denkt einfach alles toll.
Ihr wolltet halt so eine Operation haben,
die nichts mit irgendwelchen anderen Operationen zu tun hat.
Was ich in solchen Fällen immer empfehle, ist,
folgendes zu schreiben, oh Gott,
wie geht das auf den Mac?
Wie kriege ich denn jetzt
das Add of Mac hin
Play Command Coup oder so, ja. Alt L,
okay, puh, puh,
wo ist denn jetzt der Teilliste, wie war das,
also lass uns mal so, dass man im Kloster reingeht.
Irgendwie scheint es nicht mehr offen zu sein, oder?
Ah, muss man ein Projekt dürfen,
ja, noch ein hohen Projekt.
Hier? Das hier,
geklickt hat.
Ah, gut. Was wollte ich machen? Ah,
genau, ich wollte euch zeigen. Also wie alt?
Alt L? Ah, toll. Gut. Sowas könnt ihr schreiben.
Ja, ihr könnt da so schreiben, pass auf,
es gibt so eine Standard-Implementation aus Object und ich will die jetzt ersetzen.
Ja, Override heißt so viel wie ersetzen oder eine Alternative anbieten.
Und jetzt wird der Compiler sagen, du hast dich wahrscheinlich irgendwie vertan, lieber Programmierer.
Es gibt keine Methode Hashcode in Object, die du ersetzen könntest.
Ah, natürlich nicht. Ich habe mich hier ja vertippt.
Ich meine ja natürlich eigentlich diese hier. So, dann
würde er das akzeptieren. Das ist also eine Sicherheit,
die ihr für euch in euren Quelltext einbauen könnt,
zu sagen, ich will hier eine Operation ersetzen,
die es normalerweise in Object gibt.
Und lieber Compiler, erinnere mich doch wieder daran,
falls ich mich hier vertüpe.
Das kann man
hier genauso machen
Alt-L, overright, das wird funktionieren. Und wenn ihr zum Beispiel irgendwann mal so,
ja, einen schlechten Tag habt, ja, anstatt obcheckt,
sagt ihr irgendwie direkt Tag an dieser Stelle,
dann würde euch der Compiler sagen, es gibt keine Operation Equals,
die einen Tag entgegennimmt in Object.
Ja, das hilft enorm, solche blöden Fehler im Voraus zu erkennen.
Gut. Gibt es noch Fragen zu Equals, uns zu Hashgoat
? Ja. Seit der 15. Folge haben wir,
nachdem, kommt der, in viel Tag,
ganz klar
Viele auch einen anderen, durch das Leben von einem Unternehmen,
das eine der frakzeptierten Persönlichkeiten, besondere Formen von Heilung zu befinden.
So zum Beispiel? Das probieren wir einfach mal aus.
Ich würde vermuten, dass zur Laufzeit der Compiler hier sagt,
Class Cast Acception oder irgendwie sowas. Das probieren wir einmal aus.
Was muss ich denn tun, um das zu provozieren?
Eigentlich gar nichts Besonderes. Ich kann ja einfach mal
ein Objekt mit sich selbst zum Beispiel vergleichen.
Das mache ich doch mal kurz. Also sage ich Tag A
gleich New Talk. Und wenn ich sage A. Equals A,
dann müsste es jetzt irgendwie knallen, weil es ist ja
kein Strengen.
Müsstest du jetzt
eigentlich knallen
Klaas Cas Acception, juhu, ein Sneakers für Fred.
Gut. Ja. Da kann man sich also auch nicht
ins Knie schießen. Ja, sehr gute Frage.
Ja. Noch weitere Fragen? Okay, dann tut,
das tut mir leid mit der technischen Störung.
Ich werde wieder mein Altersbetriebssystem hier darauf installieren und
im neuen Jahr sehen muss und hoffentlich wieder ohne Probleme.
Vielen Dank an euch