Vererbung, Zugriffsebenen, Zugriff bei Klasse und Instanz

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 24 Antworten in diesem Thema. Der letzte Beitrag () ist von ErfinderDesRades.

    Vererbung, Zugriffsebenen, Zugriff bei Klasse und Instanz

    Hallo,

    ich hätte ein paar Fragen zu obigem Thema.

    was ist eine Assembly bzw. damit einhergehend wann funktioniert Public, aber Friend nicht?

    Dann habe ich mal geschaut wann man auf etwas zugreifen kann und wann nicht, dies sind die Methoden die alle für mich funktionieren, aber der Unterschied ist mir nicht ganz klar. Shared habe ich damit eigentlich gut verstehen können
    Wann würde ich mit einer Instanz arbeiten wollen und wann mit einer Klasse? Unterscheiden sich die Arten wie ich die Variablen zuweise?

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Test 1(Klasse Zuweisung später):
    2. Public Class Form1
    3. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
    4. A.a = 3
    5. lblShow.Text = A.a
    6. End Sub
    7. End Class
    8. Public Class A
    9. Friend Shared a As Integer
    10. End Class
    11. '-------------------------------
    12. Test 2(Klasse direkte Zuweisung):
    13. Public Class Form1
    14. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
    15. lblShow.Text = A.a
    16. End Sub
    17. End Class
    18. Public Class A
    19. Friend Shared a As Integer = 3
    20. End Class
    21. '----------------------------
    22. Test 3(Instanz Zuweisung später):
    23. Public Class Form1
    24. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
    25. Dim AInstanz As New A
    26. AInstanz.a = 3
    27. lblShow.Text = AInstanz.a
    28. End Sub
    29. End Class
    30. Public Class A
    31. Friend a As Integer
    32. End Class
    33. '----------------------------
    34. Test 4(Instanz direkte Zuweisung):
    35. Public Class Form1
    36. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
    37. Dim AInstanz As New A
    38. lblShow.Text = AInstanz.a
    39. End Sub
    40. End Class
    41. Public Class A
    42. Friend a As Integer = 3
    43. End Class
    44. '-----------------------
    45. Test 5 (Instanz Zuweisung in Instanzierung):
    46. Public Class Form1
    47. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
    48. Dim AInstanz As New A(3)
    49. lblShow.Text = AInstanz.a
    50. End Sub
    51. End Class
    52. Public Class A
    53. Friend a As Integer
    54. Public Sub New(value As Integer)
    55. a = value
    56. End Sub
    57. End Class


    Dann habe ich noch gesehen ich spare mir die Benennung der Klasse bei Vererbung, ist das der Hauptsinn von Vererbung? Und ich brauche auch kein Shared obwohl ich mit einer Klasse arbeite, wie kommt das?
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Test 6 (mit Vererbung):
    2. Public Class Form1
    3. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
    4. Dim AInstanz As New A
    5. lblShow.Text = AInstanz.a
    6. End Sub
    7. End Class
    8. Public Class A
    9. Inherits B
    10. Friend a As Integer = b
    11. End Class
    12. Public Class B
    13. Protected b As Integer = 3
    14. End Class
    15. '--------------------------
    16. Test 7 (ohne):
    17. Public Class Form1
    18. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
    19. Dim AInstanz As New A
    20. lblShow.Text = AInstanz.a
    21. End Sub
    22. End Class
    23. Public Class A
    24. Friend a As Integer = B.b
    25. End Class
    26. Public Class B
    27. Friend Shared b As Integer = 3
    28. End Class


    Und zu guter letzt wieso kann ich Inherits A bei der Form1 nicht verwenden? Eigentlich wollte ich das da testen, aber da das nicht ging habe ich noch die Klasse B aufgemacht.

    Viele Grüße

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „Haudruferzappeltnoch“ ()

    Danke, bis auf die erste Frage geht das aber etwas in eine andere Richtung. Wenn ein Programm läuft ist das dann ein Projekt, oder? Aber da können mehrere Assemblys dran beteiligt sein oder?

    Bei dem Rest gehts mir vorwiegend darum ein Gefühl dafür zu kriegen was kosmetisch/komfortabel und was notwendig ist.
    Klar, hätte ich selbst drauf kommen können. Zwei Instanzen erzeugen und dann unterschiedlich behandeln
    Da hab ich direkt mal was anderes probiert, wenn ich eine Instanz erstelle, wo die Variable Shared ist und die Klasse als zweite Instanz missbrauche, dann krieg ich da eine Notiz, aber der Code läuft wie wenn ich zwei Instanzen verwenden würde. Nur das ich dann Shared natürlich weglassen kann.

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
    3. lblShow1.Text = A.a
    4. Dim AInstanz As New A
    5. AInstanz.a = 5 'qualifizierender Ausdruck wird nicht ausgewertet
    6. lblShow2.Text = AInstanz.a 'qualifizierender Ausdruck wird nicht ausgewertet
    7. End Sub
    8. End Class
    9. Public Class A
    10. Friend Shared a As Integer = 3
    11. End Class


    Was ist denn der qualifizierende Ausdruck?

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „Haudruferzappeltnoch“ ()

    Wenn du eine Shared-Variable hast, ist diese für alle Instanzen gleich. Alle sehen dasselbe und denselben Speicherbereich.
    Wenn du diese
    Shared-Variable von außerhalb aufrufen willst, schreibst du nicht Instanzenname.MeineSharedVar , sondern Klassenname.MeineSharedVar

    Habe mal etwas rausgesucht: Diese Funktion ist auch
    Shared. Darf sie auch sein, denn sie beinhaltet keine instanz-abhängigen Variablen. Also nichts, was von Instanz zu Instanz anders sein könnte.

    VB.NET-Quellcode

    1. Private Shared Function Rotate_around_the_x_axis(ByVal vec As Vector3D, ByVal angle As Double) As Vector3D
    2. Return New Vector3D(vec.X,
    3. vec.Y * Math.Cos(angle * Math.PI / 180.0) - vec.Z * Math.Sin(angle * Math.PI / 180.0),
    4. vec.Y * Math.Sin(angle * Math.PI / 180.0) + vec.Z * Math.Cos(angle * Math.PI / 180.0))
    5. End Function


    Ob eine Funktion Shared sein darf, findest du heraus, indem du dir den FxCopAnalyzer herunterlädst. Dieser gibt dir eine Mitteilung. Aber Vorsicht: Der FxCopAnalyzer warnt sehr viel, wenn der Tag lang ist.


    Edit: @Haudruferzappeltnoch Hier ist Beispielcode für Shared-Variablen
    FormMain.vb

    VB.NET-Quellcode

    1. Public Class FormMain
    2. Private Test As New ClassX
    3. Private Test2 As New ClassX
    4. Private Sub Button_load_Click(sender As Object, e As EventArgs) Handles Button_load.Click
    5. ClassX.BMP = New Bitmap("meinPfad.jpeg")
    6. Test.Haudruferzappeltnoch = 2
    7. Test2.Haudruferzappeltnoch = 4
    8. End Sub
    9. End Class


    mit der Klasse ClassX

    VB.NET-Quellcode

    1. Public Class ClassX
    2. Public Shared BMP As System.Drawing.Bitmap
    3. Public Haudruferzappeltnoch As Integer = 1
    4. End Class

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „Bartosz“ ()

    Haudruferzappeltnoch schrieb:

    Aber da können mehrere Assemblys dran beteiligt sein oder?
    Ein Projekt mit mehreren DLLs hat mehrere Assemblies.
    Mit Public und Protected kannst Du in diese Assembly reingreifen, ansonsten nicht.
    VB.NET ist da eher großzügig, alles wird per Default Public deklariert, C# ist da restriktiver.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @Haudruferzappeltnoch Die Klasse ist der Bauplan, die Instanz der Bau.

    Quellcode

    1. Instanz = NEW (Klasse)
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    Haudruferzappeltnoch schrieb:

    Die Klasse ist quasi eine Instanz von sich selbst, aber mit komischen Einschränkungen.
    Was du meinst, gilt nur für die Form-Klasse und das auch nur in VB.Net wegen idiotischem Kompatibilitätsverhalten zu VB6.
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --
    Hallo nochmal,

    bezüglich der Vererbung habe ich nun gelernt wofür man das eigentlich machen möchte, aber bei den Propertys versteh ich nicht ganz wie das funktioniert. Habt ihr vielleicht irgendwo Beispielcode rumliegen bei dem eine vererbte Property überschrieben wird? Da hängt ja immer so eine Membervariable dran, die kann man aber nicht überschreiben.
    Public Overrides ReadOnly Property Exists As Boolean
    Member von "System.IO.FileInfo"

    @ErfinderDesRades Das Thema hatten wir schonmal. Erinnerst du dich? Damals hast du gesagt „gelungenes Klassendesign“.
    ein paar Fragen zu Zugriffs-Modifikatoren
    Bilder
    • Screenshot 2022-04-28 173953.png

      68,86 kB, 1.297×884, 37 mal angesehen
    Jetzt haste aber nur die halbe Wahrheit. Bei weiterer Recherche stellst Du fest, dass die Basisklasse diese Property als abstract/MustOverride deklariert, sodass die Erben selber festlegen müssen wann die Property True ist.

    Quellcode

    1. //
    2. // Zusammenfassung:
    3. // Ruft einen Wert ab, der angibt, ob die Datei oder das Verzeichnis vorhanden ist.
    4. //
    5. // Rückgabewerte:
    6. // true, wenn die Datei oder das Verzeichnis vorhanden ist, andernfalls false.
    Somit macht die Basisklasse nur klar: »Ok, wer von mir erbt, muss beim Thema Exists konkret werden. Aber wie das aussieht, ist mir egal.«
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Im Objektkatalog seh ich nicht wie das gecodet ist, außerdem verschleiern die anderen Sachen das vielleicht auch etwas.

    Ich habe ein bisschen rumprobiert, man will ja eigentlich möglichst viel von der vererbten Klasse nutzen, darum vererbt man es ja, aber bei der Property kann man nicht alles nutzen. Ich denke mal man greift nich einfach nach den Membern der vererbten Klasse oder? Was macht hier den Unterschied und warum wird die _Test im ersten Beispiel nicht mit vererbt? Oder darf man nur die Kurzschreibweise für Properties nicht verwenden, wenn man die vererben will?

    VB.NET-Quellcode

    1. Friend Class A
    2. Friend Overridable Property Test as Integer 'Hier wird irgendwie auch ein _Test Member erzeugt
    3. End Class
    4. Friend Class B
    5. Inherits A
    6. Private _Test as Integer 'Den brauch ich hier aber trotzdem
    7. Friend Overrides Property Test as Integer
    8. Get
    9. return -1 * _Test
    10. End Get
    11. Set(value as Integer)
    12. _Test = value
    13. End Set
    14. End Property
    15. End Class


    VB.NET-Quellcode

    1. Friend Class A
    2. Protected _Test as Integer
    3. Friend Overridable Property Test as Integer
    4. Get
    5. return _Test
    6. End Get
    7. Set(value as Integer)
    8. _Test = value
    9. End Set
    10. End Property
    11. End Class
    12. Friend Class B
    13. Inherits A
    14. Friend Overrides Property Test as Integer
    15. Get
    16. return -1 * _Test
    17. End Get
    18. Set(value as Integer)
    19. _Test = value
    20. End Set
    21. End Property
    22. End Class


    VB.NET-Quellcode

    1. Friend Class A
    2. Friend Overridable Property Test as Integer
    3. End Class
    4. Friend Class B
    5. Inherits A
    6. Friend Overrides Property Test as Integer
    7. Get
    8. return -1 * MyBase.Test
    9. End Get
    10. Set(value as Integer)
    11. MyBase.Test = value
    12. End Set
    13. End Property
    14. End Class


    Ich weiß nicht wie ich verdeutlichen kann wo mein Verständnisproblem liegt. Ich habe gehofft an Beispielcode, würde ich die entscheidenden Punkte erkennen.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Haudruferzappeltnoch“ ()

    Wenn Du eine Auto-Property erbst, dann kannst Du sie normal nutzen.
    Wenn Du eine MustOverride Property erbst, dann musst Du sie selbst implementieren, indem Du sie in der Folgeklasse mit Overrides markierst und selber implementierst, entweder als AutoProperty oder als vollständig formulierte.
    Overridable heißt: Du kannst sie aus der Basisklasse übernehmen oder Du schreibst Deine eigene. MustOverride bedeutet, dass Du sie selber implementieren musst.

    In Deinem ersten CodeBlock wird _Test implizit durch Verwendung der AutoProperty bereitgestellt, ist aber automatisch Private und damit nicht von Erben zugänglich.
    Wenn Du eine vollqualifizierte Property in der Erbenklasse willst, musst Du auch eine passende Variable in jener Klasse einbauen.

    In den anderen CodeBlocks wird eben jene BaseClass-Variable entweder durch Protected zugänglich gemacht bzw. gar nicht genutzt. Ok, alles soweit erklärbar. Aber worauf willst Du hinaus?

    Ach ja, bezüglich des zitierten Codekommentars: Ich kann in VS auf das Exists gehen und dann F12 drücken oder im ContextMenu auf Gehe zu Definition. Dann kommen die Deklarationen.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    bei der AutoProperty ist das verborgene BackingField _Test Private. Deshalb können Erben es nicht verwenden.
    Hast du alsso in Listing2 richtig gemacht, dass du die Property ausformulierst, und dabei _Test als Protected deklarierst, sodass Erben es addressieren können.

    Ebenso richtig ist Listing3, wo der Erbe das BackingField eben garnet direkt anspricht, sondern über die Basisklassen-Property.



    Aber ich hab tatsächlich Mühe, sinnvolle selbstgeschriebene Beispiele für Vererbung zu finden.
    In DbPersistance vererbe ich ein bischen, weil eine MySqlPersistance ist grundsätzlich genauso gestrickt wie eine SqlPersistance wie eine OleDbPersistance - daher habe ich deren Gemeinsamkeiten in eine Basisklasse ausgelagert.

    ansonsten hast du glaub auch meine Helpers - vielleicht kommt da ja iwo das Wort Inherits vor.
    Aber meist werden dort wohl Klassen des Frameworks beerbt - keine Selbstgeschriebenen.


    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „ErfinderDesRades“ ()

    Haudruferzappeltnoch schrieb:

    VB.NET-Quellcode

    1. return -1 * _Test
    Machst Du

    VB.NET-Quellcode

    1. return -_Test
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    ErfinderDesRades schrieb:

    Ebenso richtig ist Listing3, wo der Erbe das BackingField eben garnet direkt anspricht, sondern über die Basisklassen-Property.

    Ok, wenn man das so machen darf, ist es natürlich die kürzeste Variante. An welcher Stelle stehen denn MyBase-Member bei einem Erben? Das wirkt als wenn der Erbe versteckt seine Basisklasse mit instanzieren muss, damit der Zugriff so gelingt.

    Kann es sein, dass für die vererbten Member immer die Member der Basisklasse benutzt werden, wenn es keine Überschreibung oder Shadowing gibt?

    Und dann empfiehlt mir das Studio wenn ich gar nichts definiere (Shadows, Overrides) für eine kopierte Property, dass ich Overloads davor schreibe. Das ist nochmal was anderes. Bei Überladungen hat man ja normalerweise die Wahl welche man nutzt per Argumente.
    Ich habe Microsofts Tabelle zum Vergleich von Shadows und Overrides gesehen und muss sagen, dass ich nicht genau weiß was da vermittelt werden soll.
    Geht das alles schon zu tief und ist großteils irrelevant?

    Haudruferzappeltnoch schrieb:

    An welcher Stelle stehen denn MyBase-Member bei einem Erben? Das wirkt als wenn der Erbe versteckt seine Basisklasse mit instanzieren muss, damit der Zugriff so gelingt.
    Ich versteh die Frage nicht. Der Erbe ist doch ein MyBase. Daher hat er automatisch die nicht-Private Member in sich drin. Da muss nix heimlich instanziiert werden. Und wird auch nicht.

    Haudruferzappeltnoch schrieb:

    Kann es sein, dass für die vererbten Member immer die Member der Basisklasse benutzt werden, wenn es keine Überschreibung oder Shadowing gibt?
    Ja, aus oben genanntem Grund.

    Overloads: Du willst ne Methode verwenden, die in der Basisklasse mit dem Namen schon vorhanden ist, auch wenn ggf. andere Parameter verwendet werden. Das benutze ich, wenn ich eine Klasse habe, die von List(Of MeinTyp) erbt. Dann kann ich nicht einfach eine Sub Add nehmen, weil es die schon in der List(Of) gibt. Also muss ich Overloads verwenden, damit sie in meiner Klasse zusätzlich zu der Basisklassenmethode existieren kann.
    Shadows: Basisklassenelemente mit gleichem Namen werden unzugänglich. Würde ich meine o.g. Add-Methode so kennzeichnen, hätte ich keinen Zugang mehr zu den Add-Methoden der Basisklasse.

    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „VaporiZed“ ()