We're sorry but this page doesn't work properly without JavaScript enabled. Please enable it to continue.
Feedback

03.5.2 struct, Werttyp, Referenztyp, Teil 2

00:00

Formal Metadata

Title
03.5.2 struct, Werttyp, Referenztyp, Teil 2
Title of Series
Number of Parts
54
Author
License
CC Attribution - NonCommercial - ShareAlike 3.0 Germany:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal and non-commercial purpose as long as the work is attributed to the author in the manner specified by the author or licensor and the work or content is shared also in adapted form only under the conditions of this
Identifiers
Publisher
Release Date
Language
Producer

Content Metadata

Subject Area
Genre
Social classObject (grammar)Instanz <Informatik>Function (mathematics)Variable (mathematics)IntegerNumberZahlNormaleSummationSpeicherzelleHand fanCHART <Programm>TypC sharpPointer (computer programming)Computer animation
Instanz <Informatik>Social classTypNumberZahlVariable (mathematics)Moment (mathematics)Object (grammar)Virtual memoryInequality (mathematics)Content (media)Computer animation
Computer animationDiagram
Variable (mathematics)Diagram
Instanz <Informatik>Social classComputer animation
String (computer science)Content (media)Social classInequality (mathematics)State of matterInstanz <Informatik>Computer animation
String (computer science)Content (media)Social classNumberComputer animation
Transcript: German(auto-generated)
Vor dem Lücken Text 16 noch, um den Text da gerade zu Ende zu machen. Wenn so eine Variable für eine Klasse nur die Hausnummer ist, dann wird das spannend, wenn ich diese Hausnummer an eine Funktion übergebe. Sehen Sie sich vor, Sie haben eine Funktion, die auf Meetings arbeitet.
Ich nenne sie MeetingX von mir aus, und diese Funktion macht vielleicht ganz was Blödes, sie verschiebt einfach das Meeting, was wir da gekriegt haben.
Eine Funktion, die kriegt ein Meeting und verschiebt das Meeting. Für normale Zahlenvariablen und für Structs würde ich hier eine Kopie von der Zahl oder von der Struct kriegen.
Dieses Ding hier hätte ein Leben für sich, es wäre eine eigene Speicherzelle mit eigenen Werten. Und hier würde ich dieses eigene Ding verändern und das Original würde nichts davon erfahren, weil hier eine Kopie ankommt.
Das haben wir ja schon gesehen bei den üblichen Funktionen in C, wenn Sie sowas haben wie Gebe die Summe aus, wenn Sie sowas haben in C, in X, in Y, und dann addieren Sie beide X plus gleich Y.
Sowas zum Beispiel und geben dann die Summe aus. Hier wird eine lokale Kopie von X verändert. Das X, das da ankommt, das Y, das da ankommt, sind nicht die Variablen, mit denen ich es aufgerufen habe,
sondern getrennte neue Speicherstellen. Und was ich hier mache, hat nichts mit den ursprünglichen Werten zu tun. Anders bei Klassen, bei Verweisen auf Klassen. Dieses Ding, das da ankommt, ist ja nicht die eigentliche Instanz mit all ihren Daten, was da ankommt, ist die Referenz, ein Verweis auf die Klasse.
Dann habe ich hier wieder den eigenwilligen Effekt, diese Funktion kriegt die Hausnummer, geht zu der Hausnummer und verlegt, was es da an der Hausnummer findet. Das ist aber das ursprüngliche Objekt. Also wenn ich sowas hier mache, wie nochmal K,
da kann ich die Funktion mit dem Aufruf von F von K, wenn ich diesen Aufruf hier veranstalte,
was mache ich da schon wieder falsch? Oh, F hatten wir schon mal. Gefährlich, da oben gibt es F schon mal. Wie muss das denn heißen? F, G, E, J, K, L, M. Dann fängt die Funktion jetzt eben aus M.
So ein Aufruf. Ich rufe diese Funktion auf, gebe ihr meine Hausnummer und dann wird die Funktion wieder die Instanz verstellen, auf die diese Hausnummer zeigt. Also hier ist das K.
Auf was es jetzt auch immer steht, 26. K steht auf dem 26. Jetzt führe ich diese Funktion aus. Und K zeigt auf den 6.5.
Also ich rufe meine Funktion auf mit einer Instanz von K und diese Funktion geht jetzt in diese Instanz rein und ändert etwas. Wenn Sie das mit normalen Zahlen machen, kann nicht die Zahl geändert werden, die da übergeben wird, weil Ihnen Kopie ankommt. Bei einer Klasse, hier bei einer Referenz auf eine Klasse,
kommt hier oben eine Kopie der Hausnummer an, wenn Sie wollen. Es kommt keine Kopie der Daten an, der kompletten Daten an. Es kommt nur eine Kopie der Hausnummer an. Die Hausnummer ist aber die ursprüngliche von der Klasse. Das heißt, dieser Befehl hier wird tatsächlich die Originalinstanz der Klasse verändern und nichts anderes.
Daran muss man sich so ein bisschen gewöhnen. Für den Lückentext Nr. 16. Noch mal so ein paar Beispiele. Also wenn Sie dieses haben, int 42.
Das ist ganz ohne Frage eine normale Zahl, ein Werttyp. Wenn Sie dieses N kopieren, gibt es eine zweite Speicherstelle mit demselben Wert. Und die beiden Speicherstellen sind dann unabhängig voneinander, die Sie dann haben.
Wenn Sie für dieses N eine Funktion aufrufen, kriegt die Funktion eine Kopie vom Wert und kann ihr N nicht ändern. Wenn ich dagegen ein neues Meeting baue, in dieser Form, und das Meeting heißt Klasse und nicht Struct,
wenn ich das mache, und dieses Meeting ist hier mit Klasse definiert und nicht mit Struct, dann ist das ein Referenztyp zwangsläufig.
Das heißt, wenn ich eine weitere Variable vom Typ Meeting baue, und so zuweise, dann wird die Referenz zugewiesen. Es wird nicht das ganze Objekt kopiert, es wird nur die Hausnummer kopiert.
Ein wesentlicher Referenztyp sind Arrays. Wenn Sie ein Array bauen,
ich brauche mal ein Regal für vier ganze Zahlen, ist das überraschenderweise auch ein Referenztyp. Das heißt, wenn Sie zum Beispiel dieses Array an eine Funktion übergeben, kann die Funktion im Array herumstellen.
Das haben wir schon in C gesehen. Denn in C waren Arrays eigentlich die Namen von Arrays auch Zeiger auf das erste Element. Insofern dann nicht dasselben ähnliches Verhalten wie in C. Also wenn Sie Q durch die Gegend reichen, eine Funktion weitergeben oder jemand anderem zuweisen,
dann haben Sie dieses originale Array und kein zweites. Vielleicht führe ich das mal vor. Ich setze einfach mal Q von 2 auf 13
und weise mal zu. Ein neues Array, kein neues Array, eine neue Variable von dem Typ. Array von Integer, P, Q, R auf diese Weise.
Und jetzt stelle ich Q von 2 mal um und gucke, was in R passiert. Also ich gehe mal dahin. Hier habe ich ein neues Array. Eintrag Nummer 2 ist 13.
Ich nehme die Referenz auf dieses Array namens Q in eine neue Variable von dem Typ. Sie sehen, am Anfang steht er auf 0, das gab es auch schon. In C wurde es dann 2 und 2 groß geschrieben, N, U, L, L groß geschrieben. In Java und in C Sharp heißt es 0.
Kleingeschrieben, um zu sagen, es gibt noch keinen Verweis hier drin. Das verweist auf nichts. Ich habe keine Hausnummer, also auch nicht die Hausnummer 0 als Zahl, sondern ich habe keine Hausnummer. Dafür steht dieses 0 dann null. Jetzt kommt die Zuweisung im nächsten Schritt.
In R steht jetzt tatsächlich ein Verweis auf das Array. Es ist ein und dasselbe Array wie hier oben. Es ist ein Regal gebaut worden. Ein Regal mit vier Fächern für Integers. Dieses R weiß auch wieder nur, wo das Regal steht. In welcher Etage, links oder rechts, in welchem Zimmer.
Das R ist nicht eine komplette Kopie des Regals. Das sieht man jetzt bei dem nächsten. Wenn ich im Q den zweiten Eintrag auf 42 ändere, dann ist im Q natürlich die 42 drin. Wenn Sie jetzt bei R gucken, ist auch da die 42 drin.
Bei Arrays dasselbe. Dieses Ding gibt es nur einmal im Speicher. Einmal habe ich mir die Hausnummer unter dem Namen Q gemerkt, und einmal habe ich die Hausnummer unter dem Namen R gemerkt. Es hängt also immer vom Typ ab, den man gerade baut. Ein Meeting ist eine Klasse.
Das System wird automatisch ein Referenztyp. Das System merkt sich nur die Hausnummer. Eine Zahl bleibt ein Werttyp. Es gibt Möglichkeiten das anders zu machen, aber das will ich jetzt niemand gar nicht erwähnen. Typischerweise, nein, 99,9% sind die Zahlen Werttypen.
Das sehen Sie gar nicht anders. Das heißt, wenn Sie die zuweisen, haben Sie eine neue Kopie gebaut von der Zahl. Diese hier sind Structs. Die verhalten sich wie die Zahlen. Es kommt also auf den Typ an. Habe ich einen Referenztyp, eine Klasse,
eine Instanz einer Klasse, oder habe ich einen Werttyp? Praktisch alles andere. Je nachdem ist das Verhalten verschieden. Eine letzte Geschichte zu diesem haarigen Thema.
Vergleiche. Ganz übel. Was passiert, wenn ich jetzt vergleiche? Wenn Sie zwei Zahlen vergleichen, dann gucken Sie, ob in beiden derselbe Wert drin steht. Wenn Sie zwei Daytimes vergleichen, dann gucken Sie hoffentlich auch, ob das der selbe Zeitpunkt ist. Noch ein Thema für sich.
Aber wenn ich zwei Instanzen von Kassen vergleiche, dann kann es kompliziert werden. Machen wir noch mal ein neues Meeting. PQRS.
Ahnung von drei Stunden. Ja, kommt schon. Ah nein, ich sollte doch den ganzen Perzaktor nehmen. Entschuldigung. Ich sollte doch den ganzen Perzaktor nehmen. Date Time Wedding.
Kriege ich mal eine sinnvolle Date Time. Date Time. Ich brauche jetzt mal eine feste Date Time. Ah, andersrum. Entschuldigung. Man sollte erst nachdenken und dann schreiben, ich brauche mal eine Date Time. PQRST.
Alles passt ja super. Ist gleich nur Date Time. Nein, ich will nicht du Date Time. Ich will datetime. Irgendwas sinnvolles. Nehmen wir mal den wieder. So, ein neues Meeting bauen. Aktuelle Zeit. Wie lang soll es sein? Timespan.
.from Minutes von mir aus. 90 Minuten soll es sein. Und es soll irgendeinen dummen Titel haben. So. Und ich baue noch ein Meeting. PQRST. Uh. Was doch verdammt ähnlich aussieht.
Mit denselben Daten drin. Jetzt kommt eigentlich keine Überraschung. Wenn man 2 Minuten nachdenkt, ist das eigentlich keine Überraschung, was jetzt passiert für Klassen. Ich schreibe hier mal rein.
Hier schreibe ich mal rein. 1 Punkt. Content ist gleich. Was auch immer. Wird diese Zeile ausgeführt oder nicht?
Gucken wir uns das an. Ich setze meinen Breakpoint auf den Vergleich. Jetzt kommt der spannende Moment. Zack, drüber gesprungen. Er geht nicht rein. Es ist nicht gleich U.
Das ist am Anfang total irritierend. Ich weiß. Gucken Sie sich an, was da steht. Wortwörtlich. Nehmen Sie wirklich Wortwörtlich, was da steht. Es wird ein neues Meeting gebaut. Und dessen Hausnummer landet in S. Und dann wird noch ein neues Meeting gebaut. Das hat dieselben Daten wie das davor. Aber dessen Hausnummer muss eine andere sein,
denn das ist ein neues Meeting. Die landet in U. Also sind die beiden Hausnummer nicht gleich. Was hier verglichen wird, sind die Referenzen, die Hausnummer. Das sind zwei eigenständige Objekte mit denselben Daten drin. Sie kaufen dasselbe Auto zweimal. Es ist blau, hat 4 Räder, was auch immer. Sie kaufen dasselbe Auto zweimal.
Aber das sind zwei verschiedene Autos in diesem Simmel. Das sind zwei verschiedene Objekte. Zwei verschiedene Hausnummer. Sollte man sich das nochmal aufmalen, was da passiert. Also es wird erst eine neue Meeting gebaut in der ersten Seite.
Und dann wird noch ein Meeting gebaut. Ein zweites Meeting. Ich habe die Variable S, die sich merkt, an welcher Stelle das erste Meeting steht. Ich habe die Variable U, die sich merkt, an welcher Stelle das zweite Meeting steht.
Und das ist die Hausnummer 10.000 so und so viel. Und das ist die Hausnummer 40.000 so und so viel. Diese beiden Hausnummer sind nicht dieselben Hausnummer. Auch wenn in den beiden Meetings exakt dasselbe drin steht, stehen die nicht unter derselben Hausnummer.
Das wäre für sich noch relativ einfach hinzukriegen, wenn das grundsätzlich so wäre. Aber wenn Sie zwei Instanzen einer Klasse haben und vergleichen die, wenn das immer so wäre, dass dieses Gleich-Gleich einfach nur sagt, ob es wirklich ein und dieselbe Instanz ist.
Ich könnte jetzt zum Beispiel so was machen. U gleich S. Dann ist ein und dieselbe Instanz. Das sind dieselben Hausnummer. Und er muss hier reingehen. Wir sehen, ich bin da drin. Das funktioniert also tatsächlich. Er vergleicht die Hausnummern. Er vergleicht nicht die Werte.
Das Üble ist jetzt, wenn Sie die Klasse richtig bauen, in Anführungszeichen richtig bauen, können Sie dafür sorgen, dass dieses Gleich-Gleich die Werte vergleicht. Das heißt, je nach Klasse ist dieses Gleich-Gleich ein Vergleich der Hausnummern, der Referenzen oder ein Vergleich der Inhalte. Das ist tückisch.
Also zwei Stellen an diesem Spiel sind tückisch. Die erste Stelle, die tückisch ist, dass man sich klar machen muss, ob das, was man da verwendet, ein Struct ist oder eine Klasse ist. Das Verhalten wird anders sein, je nachdem ob es ein Struct oder eine Klasse ist. Und die andere tückische Stelle ist diese hier. Wenn Sie Gleich-Gleich schreiben,
kann das bedeuten, Prüfe, ob die Hausnummern gleich sind oder ungleich. Das ist natürlich dann das Analoge, sind die Hausnummern ungleich. Ein Vergleich auf die Hausnummern, gleich oder ungleich sind, sind es wirklich dieselben Instanzen, ein und dasselbe Ding. Eine Möglichkeit, aber wenn die Klasse
ein bisschen komplizierter gebaut ist, ist dieses hier wirklich ein Vergleich der Inhalte. Das haben wir zum Beispiel bei den Strings. Die sind so gebaut. T, S, U, V weiter. Eine Zeichenkette. Test.
Und eine weitere Zeichenkette. U, V, W. Die ich jetzt auch Test nenne. Und nun vergleiche ich. Das haben wir ja schon tausendmal gemacht. Insofern keine Überraschung, was passiert. Der geht in das If rein.
Weil String etwas komplizierter gebaut ist, sodass dieses Gleich-Gleich tatsächlich nicht nur Hausnummern vergleicht. Wenn ihr nicht schadet, das einmal nachzuvollziehen.
Und da bin ich drin. Dieser String ist tatsächlich gleich dem String. Da funktioniert das Gleich-Gleich anders. Das ist eher ungeschickt. Je komplizierter die Klassen sind,
desto mehr muss man dann aufpassen. Es sollte eigentlich nicht so sein. Je komplizierter die Klassen sind, umso besser wäre es eigentlich, wenn man dieses Gleich-Gleich nicht überraschend baut. Wenn dieses Gleich-Gleich für alles, was mit Klassen ist, die Hausnummer vergleicht, die Referenzen vergleicht, aber nicht die Inhalte vergleicht. Aber Sie sehen bei den Strings,
ganz dreist, vergleicht er die Inhalte. Und wenn jemand eine Klasse raffiniert baut, kann die so gebaut sein, dass tatsächlich dieses Gleich-Gleich die Inhalte vergleicht. Jetzt aber nochmal die beiden spannenden Punkte. Die beiden spannenden Punkte sind, wenn Sie so etwas haben wie Date-Time, Type-Spend
oder Meeting, müssen Sie erst gucken, ist das eine Struct oder ist das eine Klasse. Je nachdem verhält sich das hier anders. Es werden Referenzen gespeichert oder echte Werte gespeichert. Und, wenn Sie Gleich-Gleich machen, hängt das je nach
Ding, was man da gerade hat, wird das hier tatsächlich die Inhalte vergleichen oder wird die Hausnummern vergleichen. Ab Werk wird es die Hausnummern vergleichen, außer bei Strings, wo es ab Werk schon die Inhalte vergleicht. Das ist ein allgemeines
Ärgernis in den neuen Sprachen.