Zum Inhalt springen
L

Das Video kommt von YouTube: erst beim Abspielen verbindet sich die Seite mit YouTube (Google).

Grundlagen der Informatik 2, Vorlesung 8: Zugriffskontrolle

Sebastian Küpper23:42 114 Aufrufe veröffentlicht Auf YouTube

Das Wichtigste aus dem Video

Tipp auf eine Zeit – das Video springt genau dorthin.

Transkriptautomatisch erstellt · 159 Zeilen
Herunterladen
  1. Hallo liebe Fernstuden und herzlich willkommen zur achten Vorlesung zum Kurs Grundlagen der Informatik 2. In dieser Vorlesung werden wir uns mit
  2. Zugrskontrollen befassen. Sie haben ja bereits in der Vergangenheit gesehen, dass wenn wir Zugriff erlauben wollen auf bestimmte Attribute oder Methoden,
  3. wir hierfür Schlüsselwörter verwenden müssen, wie beispielsweise public. Und in dieser Vorlesung wollen wir einmal systematisch darüber sprechen,
  4. welche Schlüsselwörter es gibt und welche Bedeutungen diese in C#ARP haben. Wir beginnen mit der Diskussion der Zugriffskontrolle auf der obersten
  5. Ebene, auf der Zugriffskontrolle eine Rolle spielt und zwar bei den Namensräumen oder auch in anderen Programmiersprachen manchmal Pakete
  6. genannt. Also in Java heißen die z.B. Pakete. In C#ARP können Klassen in Namensräumen gebündelt werden. Das heißt, wir können
  7. Namensrä Räume definieren und darin verschiedene Klassen anbieten. Wir definieren einen Namensraum über das Schlüsselwort Namespace, das oberhalb
  8. der Klasse angegeben werden muss. Also, wenn wir eine Klasse in einen Namespace packen wollen, dann müssen wir oberhalb der Klasse schreiben Namespace und dann
  9. den Namen des Namensraums schreiben. Namespaces dienen dazu, dass man einen Gültigkeitsrahmen für Namen festlegen kann. Also, wenn wir einen Klassennamen
  10. verwenden innerhalb eines Namensraums, dann kann es nicht eine zweite Klasse haben, die den gleichen Namen trägt im gleichen Namensraum. Aber wenn wir einen
  11. anderen Namensraum nutzen, dann können wir den gleichen Namen wieder verwenden. Das heißt, wenn wir einen ersten Namensraum A haben und einen zweiten
  12. Namensraum B haben, dann können wir sowohl in A als auch in B verschiedene Klassen namens vielleicht K haben, also der gleiche Name für die Klasse, sowohl
  13. in Namensraum A als auch in Namensraum B. Und diese beiden Klassen haben dann nichts miteinander zu tun. Wohingegen, wenn man innerhalb eines Namensraums
  14. arbeitet, dann kann es immer nur eine Klasse mit einem Namen geben. Nun ist es aber natürlich so, dass man äh eventuell nicht nur innerhalb eines
  15. Namensraums arbeiten möchte und man kann auf Klassen anderer Namensräume zugreifen. Wir können das entweder machen, indem wir die Namensräume
  16. explizit vorher erwähnen, also wenn wir jetzt z.B. Beispiel von vorhin nehmen, dass wir in Namensraum A und in Namensraum B jeweils eine Klasse K
  17. haben. Dann können wir sowas schreiben wie A.K oder B.K, und K, um auf die jeweilige Klasse aus dem Namensraum A oder B zuzugreifen. Außerdem können wir
  18. auch sagen, dass wir einen Namensraum komplett einbinden. Dafür können wir oben in der Klassendatei schreiben using und dann den Namen des jeweiligen
  19. Namensraums. Dadurch wird die Klasse, in der wir gerade arbeiten, nicht in den Namensraum hinzugefügt, aber wir können alle Klassen, die in diesem Namensraum
  20. definiert sind, anschließend verwenden, als wären sie im gleichen Namensraum. Das heißt, wir müssen sie nicht mehr qualifizieren. Wir könnten also, wenn
  21. wir den Namensraum A einbinden, einfach den Namen K verwenden, ohne dass wir sagen, dass wir das K aus Namensraum A nehmen. Zumindest solange wir nicht auch
  22. noch einen anderen Namensraum einbinden, indem der gleiche Name auch definiert wird. Schauen wir einmal ein Beispiel dafür
  23. an, wie ein Namensraum eingebunden wird. Wir definieren hier eine Klasse Order in dem Namensraum Customer und wir wollen in der Klasse Order die Klasse Article
  24. List nutzen. Und die Klasse Articleist ist aber nicht Teil des Nampaces Customer, sondern des Namensraums Flowershop. Was wir also machen können,
  25. ist, dass wir oben eine Using Direktive angeben und wir sagen using flowershop.articlist. Wenn wir das machen, dann können wir im
  26. Rest der Datei auf den Namen Articellist zugreifen, ohne da jeweils Flowershop davorzuschreiben. Das sehen wir hier jetzt in dem
  27. Beispielscode. Was wir auch tun könnten, wäre den gesamten Namensraum Flowershop einzubinden. Dann würden wir einfach nur schreiben using Flowershop. Allerdings
  28. hätte das zurfolge, dass wirklich alles, was in dem Namensraum ist, eingebunden würde. Und das hieße jetzt für uns hier, dass wir bei unserer Namensgebung darauf
  29. achten würden, dass wir nicht nur keine Kollision zu den konkret eingebundenen Klassen haben, sondern dass wir keine Kollision zu irgendeiner Klasse in dem
  30. Namensraum haben. Und darum ist es häufig besser, wenn man nur einzelne Klassen einmittet, zumindest wenn man nicht sowieso sehr viel Funktionalität
  31. aus dem anderen Namensraum benötigt. Hier sehen wir jetzt noch einmal, wie das dann tatsächlich aussieht im Code. Wenn wir einen ganzen Namensraum
  32. einbinden, dann schreiben wir also so etwas wie hier using Flowershop und ansonsten ändert sich im Vergleich zu unserem vorherigen Code nichts.
  33. Eine wichtige Sache, die vielen Menschen erst einmal nicht klar ist und vielleicht sogar unintuitiv erscheint, ist der Umstand, dass Unternamensräume
  34. separat importiert werden müssen. Das heißt, wenn wir hier so zwei Zeilen haben, using A und using A.B. B, dann ist die zweite Zeile nicht redundant.
  35. Der Unternamensraum B von A wird nicht automatisch mit eingebunden, wenn wir den Namensraum A entbinden.
  36. Bevor wir jetzt zu den Zugriffsbeschränkungen kommen, die für uns eine größere Rolle spielen, nämlich von den Bestandteilen einer Klasse,
  37. wollen wir zunächst einmal erklären, warum macht man das überhaupt mit Zugriffsbeschränkung, denn man könnte ja in seinem gesamten Code einfach alles
  38. auf public setzen und dadurch überall maximale Sichtbarkeit haben. Und das tut man aber nicht. Warum denn nicht? Zunächst einmal wäre da die Kontrolle
  39. des eigenen Zustandes oder auch die Koherenz. Das heißt, wenn wir keinen wahllosen Zugriff von überall her auf unsere Attribute zulassen, dann haben
  40. wir mehr Kontrolle darüber, welche Werte Attribute einnehmen können. Insbesondere können Setter dazu verwendet werden, auch zu überprüfen, ob ein neu gesetzter
  41. Wert für ein Attribut überhaupt zulässig ist. Wohingegen, wenn wir ein Attribut einfach nach außen bekannt geben, dann kann jede andere Codeelle unsere
  42. Attribute auf irgendeine Weise verändern und gegebenenfalls daranhängende andere Attribute nicht berücksichtigen oder sogar illegale Werte für unser
  43. zusetzenes Attribut setzen. Außerdem haben wir eine größere Unabhängigkeit von der Implementierung, denn wir könnten uns z.B. entscheiden, dass wir
  44. eine Variable, die wir bisher verwendet haben, als Attribut abschaffen und daraus ein abgeleitetes Attribut machen. Also kein echtes Attribut mehr, sondern
  45. einen Wert, der jedes Mal, wenn er abgefragt wird, über den Getter neu berechnet wird. Wenn wir allerdings unsere Variablen sichtbar machen nach
  46. außen, dann können wir das nicht mehr ohne weiteres machen. Denn wenn wir jetzt ein Attribut entfernen und ersetzen durch ein abgeleitetes
  47. Attribut, dann hat das Zufolge, dass von außen das Verhalten nicht mehr so aussieht, wie es vorher aussah und da müssen wir gegebenenfalls auch anderen
  48. Code noch mitändern. Außerdem haben wir eine höhere Übersichtlichkeit des Interfaces und der Dokumentation, denn eine Methode, die
  49. von außen nicht gesehen wird, die muss auch nicht erläutert werden, jedenfalls nicht nach außen erläutert werden. Und das Interface wird dadurch schlanker,
  50. weil Methoden, die für Außenstehende vielleicht überhaupt keine Relevanz haben, für diese auch nicht sichtbar werden. Und das heißt, wenn Sie dann
  51. z.B. Codevorschläge bekommen, weil sie mit einem Punktoperator eine Methode auswählen wollen, dann werden auch nur solche Methoden
  52. vorgeschlagen, die für sie überhaupt eine Rolle spielen. Und wir können all diese Punkte bereits zur Kompilationszeit
  53. sicherstellen. Das heißt, wir sorgen damit auch dafür, dass wir bestimmte Aufgaben, die sich ansonsten ergeben würden, aus der Testphase oder aus der
  54. Verifikationsphase des Programms nach vorne ziehen können, sodass wir bereits zur Kompilation feststellen können, dass bestimmte Dinge nicht passieren können.
  55. Beispielsweise oben, was wir angesprochen haben, dass ein nichtkohärenter Zustand eines Objekts von außen her induziert wird.
  56. kommen wir dazu, welche Sichtbarkeiten wir beschränken wollen. Und da gibt es im Grunde drei Stellen, an denen wir Sichtbarkeiten gegebenenfalls
  57. modifizieren wollen. Das wären Klassen, Methoden und Attribute. Wobei wir sehen werden, bei Klassen ist es hier scharf bezüglich der Sichtbarkeit nicht so viel
  58. zu machen. Bezüglich Methoden und Attributen haben wir aber einige Möglichkeiten, die wir auch kennenlernen und nutzen sollen. Bei den Klassen gibt
  59. es nur zwei Stufen von Sichtbarkeit und das wäre einmal die Standardsichtbarkeit, die erfolgt, wenn man einfach überhaupt keinen
  60. Zugsmodifikator angibt und andererseits die public Sichtbarkeit. Dafür müssen wir den Zugsmodifikator public angeben. Die Public Sichtbarkeit bedeutet, dass
  61. man wirklich von überall aus die Klasse aufrufen kann. Insbesondere und das ist der entscheidende Unterschied von jedem Assembly aus. Das heißt, wenn wir unser
  62. Assembly beispielsweise als DLL anbieten, dann kann von einem anderen Assembly aus auf diese Klassen, die als public markiert sind, zugegriffen
  63. werden. Für Klassen, die die Standardsichtbarkeit haben, ist ein solcher Zugriff in einem anderen
  64. Assembly aber nicht möglich. Und das ist auch der einzige Unterschied. Innerhalb eines Assemblies können wir auf Klassen mit der Standardsichtbarkeit frei
  65. zugreifen. Die einzige Voraussetzung ist das, was wir oben bereits besprochen haben, dass also wir entweder uns im gleichen Namensraum befinden, den
  66. entsprechenden Namensraum ausdrücklich einbinden oder aber einen qualifizierten Aufruf an die Klasse durchführen, also mit einem Punkt nach dem Namensraumen
  67. und dann erst den Namen der Klasse angeben. In Java ist die Standardsichtbarkeit der Klassen auf das Paket und das ist das
  68. Äquivalent des Namensraumes beschränkt. Eine solche Sichtbarkeitsklasse für Klassen gibt's in C#ARP nicht. Das heißt, wir können nicht sagen, diese
  69. Klasse kann nur innerhalb unseres Namensraums verwendet werden. Denn wenn wir eine Klasse definieren, haben wir gerade gesehen, dann ist sie ja
  70. mindestens mit Standardzugriff ausgestattet und dann können wir von jedem Namensraum im gleichen Assembly drauf zugreifen. In diesem Kurs werden
  71. wir uns aber nicht um das Einbinden von Assemblies, also DLLs kümmern. Und das bedeutet, für uns macht es überhaupt keinen Unterschied, ob eine Klasse
  72. public ist oder nicht. Sie sollten das grundsätzlich im Kopf behalten, denn wenn sie später produktiv arbeiten, könnte es durchaus mal passieren, dass
  73. sie mit Assemblies arbeiten. Aber für unseren Einführungskurs hier spielen Assembleys keine Rolle. Es gibt einen Zusammenhang zu dem
  74. Masterkurs moderne Methoden der Softwareentwicklung. Public Klassen sind solche, die dort veröffentlichte Schnittstellen genannt werden,
  75. wohingegen die Standardsichtbarkeit mit einem in diesem Kurs öffentlich genannten Namen korrespondieren. Das heißt, ein
  76. Interface, das als öffentlich bezeichnet wird in diesem Kurs ist das, was wir hier mit der Standardsichtbarkeit auffassen und das, was sogar fair
  77. öffentlicht ist, sind diejenigen Klassen, die wir hier als Public Kennzeichnen. Wenn wir die Sichtbarkeit von
  78. Klassenelementen besprechen wollen, dann müssen wir nicht unterscheiden zwischen Methoden und Attributen, denn Methoden und Attribute haben die gleichen
  79. Sichtbarkeitsklassen zur Verfügung. Diese Sichtbarkeitsklassen, das sind insgesamt sechs Stück, heißen public, protected internal, protected,
  80. internal, private protected und private. Und wir unterscheiden danach, ob wir aus der gleichen Klasse darauf zugreifen können, aus einer Kindklasse imselben
  81. Assembly oder in einem anderen Assembly, aus einer nicht abgeleiteten Klasse imselben Assembly oder in einem anderen Assembly. Und wenn wir das Schlüsselwort
  82. public verwenden, dann bedeutet das, wir können von überall darauf zugreifen. Wohingegen protected bedeutet, wir können von der eigenen Klasse aus darauf
  83. zugreifen oder von einer Kindklasse, egal ob die im selben Assembly ist oder in einem anderen Assembly. Das Schlüsselwort Internal hingegen
  84. kümmert sich nicht darum, ob es eine Kindklasse ist, sondern darum, ob wir uns imselben Assembly befinden. Das heißt, internal bedeutet, wir können von
  85. der gleichen Klasse aus, von der Kindklasse und von nicht abgeleiteten Klassen imselben Assembly auf das entsprechende Klassenelement zugreifen,
  86. aber nicht in einem anderen Assembly. Wenn man jetzt die Erlaubnisse von Protected und Internal kombinieren möchte, dann kann man den Begriff
  87. Protected Internal verwenden. Der verbietet dann nur den Zugraff auf dieses jeweilige Klassenelement von einer nicht abgeleiteten Klasse aus, die
  88. in einem anderen Assembly definiert wird. Wenn man hingegen die Stränge der beiden Elemente protected und internal kombinieren möchte, dann ist Private
  89. Protected das Richtige. Hier erlauben wir generell gar keinen Zugriff aus einem anderen Assembly und aber auch keinen Zugriff aus nicht abgeleiteten
  90. Klassen, selbst wenn die im selben Assembly sind. Und schließlich haben wir die letzte Sichtbarkeitsstufe, die auch standardmäßig ohnehin vergeben wird. Das
  91. ist also hier die Standarddichtbarkeit, das ist private. In der gleichen Klasse können wir damit noch immer auf das jeweilige Klassenelement zugreifen. Das
  92. lässt sich nie ausschließen, aber keine Kindklasse kann darauf zugreifen und auch keine Nichtkindklasse, egal ob im gleichen oder in einem anderen Assembly
  93. kann dann darauf zugreifen. Diese Zugriffsmodifikatoren, die wir oben angegeben haben, die werden vor der Deklaration angegeben und sind auch noch
  94. vor dem Begriffen Static oder Seal zu nennen. Im folgenden beschränken wir uns auf die drei Sichtbarkeitsklassen Private, Protected und Public. Und das
  95. sind auch die einzigen, die für die Prüfung relevant sein werden, denn wir befassen uns ja in dieser Vorlesung nicht mit Assemblies und die beiden
  96. anderen Sichtbarkeitsklassen spielen ja hier nur eine weitere Rolle dann, wenn man verschiedene Assemblies betrachtet. Um diese Begriffe ein wenig einzuüben,
  97. betrachten wir hier einmal ein Beispiel mit drei Klassen A, B und C, wobei B von A abgeleitet ist und C unabhängig von den Klassen A und B ist. Und jede dieser
  98. drei Klassen hat jeweils ein Attribut. Bei A heißen sie XYZ, bei B heißen sie UVW und bei C heißen sie ABC. Das private protected respektive public ist.
  99. Beginnen mit der Klasse A. Das Private Attribut X ist nur in A sichtbar, weil ja private bedeutet, dass nur die eigene Klasse es sehen kann. Dann haben wir ein
  100. Protected Attribut Y. Das ist sichtbar in A und B, denn B ist von Ageleitet. Das heißt, B kann auch darauf zugreifen und schließlich haben wir ein public
  101. Attribut Z und das ist in allen drei Klassen A, B und C sichtbar, weil es eben public ist und damit keine Einschränkung besteht bezüglich der
  102. Sichtbarkeit des Attributs. In Klasse B haben wir jetzt UV und W, wobei U private ist und damit automatisch nur in B sichtbar ist. Dann
  103. haben wir V, das ist protected. Das ist jetzt aber auch nur in B sichtbar, denn B ist zwar vom Aleitet, aber umgekehrt gibt's eine solche Relation ja nicht.
  104. Wir haben auch keine andere Klasse, die von B abgeleitet ist. Also ist V nur in B sichtbar. Und schließlich haben wir wieder eine Public Variable W und die
  105. ist in allen drei Klassen sichtbar. Und bei Klasse C stellt sich das jetzt im Grunde genauso da wie bei Klasse B. Wir haben ein private Attribut A, das ist
  106. damit auch automatisch nur in A nur in C sichtbar. Dann haben wir ein Protected Attribut B. Das ist nur in C sichtbar, denn es gibt keine von C abgeleitete
  107. Klasse. Und schließlich ein public Attribut, das auch C heißt. Und das ist sichtbar in den Klassen A, B und C, einfach, weil es eben public ist und
  108. damit keine Einstellung für die Sichtbarkeit besteht. Die Sichtbarkeitsmodifikatoren, die uns in Zuge dieser Vorlesung
  109. interessieren, nämlich Public Protected Private, lassen sich auch in der UML ausdrücken. Und zwar schreibt man dort die Sichtbarkeitsmodifikatoren, das ist
  110. jeweils nur ein Zeichen, direkt vor das jeweilige Attribut respektive die jeweilige Methode. Und für public verwenden wir das Zeichen Plus, für
  111. Protected die Raute und für Private ein Minus. Um das Ganze einmal anhand eines Beispiels zu illustrieren, habe ich hier
  112. einen kleinen Ausschnitt aus unserer Klassenhierarchie von unserem Leitbeispiel herausgegriffen und diesen Teil des Klassendiagramms
  113. einmal mit den Sichtbarkeitsmodifikatoren versehen. Wie Sie hier sehen, ist das Ganze im Grunde sehr simpel, denn alle
  114. Attribute sind hier einfach als private markiert und alle Methoden als public. Das ist nicht zwingend immer so, aber grundsätzlich bietet es sich schon an
  115. und es ist meistens zu empfehlen, tatsächlich alle Attribute private zu setzen. Und bei den Methoden ist es so, dass normalerweise in einem UML-diagramm
  116. besonders die öffentlichen Methoden eine wichtige Rolle spielen. Teilweise verzichtet man insbesondere auf die privaten Hilfsmethoden. Also, wenn man
  117. jetzt eine Methode hat, die nur als Hils Methode verwendet wird, dann ist das für die Modellierung in dem UML-diagramm nicht wichtig. Das heißt, private
  118. Methoden tauchen hier in aller Regel nicht auf. hingegen protected Methoden spielen natürlich schon eine relevante Rolle und die sind dann auch häufig in
  119. einem solchen Klassendiagramm zu finden und dann eben zu erkennen, dass da kein Plus steht, sondern eine Raute. Aber die grundlegende Idee ist schon meistens,
  120. dass man die Attribute nicht sichtbar haben möchte und die Methoden sichtbar haben möchte. Wenn wir einen Klassenmember bei einer
  121. Vererbung überschreiben und das ist jetzt etwas, was nur Methoden betrifft, dann dürfen die Zugsrechte nur erweitert werden. Das heißt, wir können von
  122. private zu protected und von Protected zu public übergehen, aber nicht umgekehrt. Das heißt, wenn etwas bereits in der Oberklasse public ist, dann kann
  123. es in der abgeleiteten Klasse nicht beispielweise auf Protected herabgesetzt werden. Ich habe vorhin bereits einmal angesprochen, dass es grundsätzlich
  124. sinnvoll und empfehlenswert ist, Attribute private zu behalten und nicht für abgleitete Klassen oder gar außenstehende Klassen sichtbar zu
  125. machen. Das nennt man auch das Geheimnisprinzip. Und dieses Geheimnisprinzip, das möchten wir jetzt einmal motivieren, indem wir
  126. ein Beispiel besprechen, bei dem ein echter Vorteil aus dem Geheimnisprinzip erwächst. Man stelle sich vor, man habe eine Klasse Complex Numbers, um die
  127. komplexen Zahlen zu repräsentieren. Und diese Klasse habe nun zwei Attribute, nämlich den Realteil und den Imaginärteil Real und Imaginary. Die
  128. haben auch jeweils einen Getter und einen Zter. Jetzt könnte es natürlich sein, dass man sich entscheidet, wir wollen vielleicht
  129. die komplexen Zahlen gar nicht über Realteilen, die Imaginärteil repräsentieren, sondern viel sinnvoller wäre es doch eigentlich das Ganze über
  130. Polarkoordinaten zu repräsentieren. Je nachdem, wie man mit diesen komplexen Zahlen rechnet, ist mal die eine und mal die andere Darstellung sinnvoller. Aber
  131. wenn man z.B. jetzt feststellt die ursprüngliche Idee das über die x und Y Koordinaten zu repräsentieren, also über den realen Imaginärteil, das ist
  132. meistens jetzt ineffizienter für das, was wir machen wollen. Dann würde man ja vielleicht das Ganze umstellen, würde entsprechend Attribute Radius und Angle
  133. einfügen und jeweils einen Getter und Zettel dafür angeben. In der Form, die wir gerade gesehen haben, wäre allerdings die Konsequenz
  134. natürlich, dass das Ganze nicht mehr kompatibel wäre mit Code, der für die alten komplexen Zahlen geschrieben wäre. Was wir aber jetzt tun könnten, ist,
  135. dass wir die Getter und Zter für die alten Realteile und Imaginärteile hier übersetzen, dass wir also sagen, wir setzen hier gar nicht mehr wirklich
  136. eine Variable real oder eine Variable Imaginary, sondern wir errechnen, was ist denn die Auswirkung auf Radius und Angle, wenn wir den Realteil oder den
  137. Imaginärteil separat setzen würden. Das heißt, der Getter ist an der Stelle relativ einfach. Wir rechnen hier einfach über die üblichen Sinus und
  138. Cosinus Funktionen aus, wie man aus dem Radius und aus dem Winkel den entsprechenden real und Imaginärteil bekommt. Und die Zter, die berechnen
  139. nun, wie man aus den kathesischen Koordinaten die Polarkoordinaten ermittelt. Das heißt, wir setzen jetzt beispielsweise den Realteil, das heißt,
  140. wir belassen den imaginärteil unverändert, den nehmen wir uns zunächst einmal mit Get Imaginary. Den berechnen wir also an der Stelle.
  141. Und dann setzen wir den neuen Winkel und den neuen Radius aus diesen kathetesischen Koordinaten, also aus den Werten Real Imaginary. Und genau das
  142. gleiche machen wir, wenn der Imaginärteil gesetzt wird. In der obigen Implementation fehlte jetzt noch die vorausgesetzte Methode
  143. Set from Cartesion. Und diese Methode würde man jetzt üblicherweise private setzen, denn das ist ja nur eine Hilfsmethode für unsere Implementation
  144. der komplexen Zahlen als Polarkoordinaten. Und diese Methode bekommt also einen Realteil, ein Imaginärteil übergeben und
  145. berechne ich jetzt einfach den Radius und den Winkel entsprechend der Zuordnungsvorschriften, die üblicherweise verwendet werden, um eine
  146. solche Transformation zwischen diesen beiden Darstellungen vorzunehmen. Die genauen Formeln müssen sie sich jetzt eigentlich gar nicht groß anschauen an
  147. der Stelle. Wichtig ist nur, wir verwenden auch hier wieder den Setter. Das heißt, selbst wenn wir uns später entscheiden würden, wieder zu wechseln
  148. zwischen den Polarkoordinaten und den Realteil und Imaginärteil, könnten wir an der Stelle mit wenig Aufwand diese Methoden immer noch beibehalten.
  149. Der große Vorteil ist jetzt an der Stelle jedenfalls, dass von außen wir überhaupt nichts verloren haben und sich nichts geändert hat für den Aufrufer,
  150. indem wir hier die Polarkoordinaten statt der realen Imaginärteile verwendet haben. Das heißt, wenn wir uns jetzt entschieden hätten, realen Imaginärteil
  151. nicht privat zu halten, dann hätten wir jetzt das Problem, dass wir alle Klassen, die unsere komplexen Zahlen genutzt haben, daraufhin überprüfen
  152. müssten, ob dort irgendeinen Zugriff auf den realen Imaginärteil stattgefunden hat und das dann jetzt auf unsere Getter und Zter umlenken oder aber komplett den
  153. Code zu ändern, um direkt mit den Polarkoordinaten zu arbeiten. Das ist natürlich jetzt ein Beispiel, dem dem sie nicht häufig zu tun haben
  154. werden, dass sie jetzt konkret die komplexen Zahlen implementieren, aber es ist etwas, was immer mal wieder vorkommen kann, dass sie abgeleitete
  155. Attribute und nicht abgeleitete Attribute haben und zwischen denen wechseln müssen. Üblich schließen wir diese Vorlesungseinheit mit drei Fragen
  156. zur Selbstdiagnose, mit denen Sie überprüfen können, ob Sie die Inhalte dieser Vorlesung gut verstanden haben. Die erste Frage ist, wozu sollte man
  157. Zugriffsbeschränkungen vornehmen? Die zweite Frage ist, was gilt für die Zugriffsmöglichkeiten auf Klassen, Attribute und Methoden, wenn man keinen
  158. Zugriffsmodifikator angibt? Und schließlich, was ist hinsichtig der Sichtbarkeitsklassen bei der Spezialisierung, also der Ableitung zu
  159. berücksichtigen? Vielen Dank für Ihre Aufmerksamkeit und bis zum nächsten Mal. M.

Zum Nachlesen