ein paar Fragen zu Zugriffs-Modifikatoren

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

Es gibt 37 Antworten in diesem Thema. Der letzte Beitrag () ist von Bartosz.

    ein paar Fragen zu Zugriffs-Modifikatoren

    Hallo,

    ich habe mir heute nochmal die Zugriffsmodifizierer in VB.NET angeschaut. Ich habe ein paar Fragen (1.1 - 1.4) und wäre erfreut, wenn ihr sie mir beantworten könntet. Unten habe ich einen Text zu Vererbung geschrieben. Könntet ihr über den Code schauen, bitte?

    1) Als Erstes zu
    Friend, Protected Friend und Private Protected.

    1.1.) Zu Protected weiß ich bereits: Eine protected Variable ist nicht sichtbar, außer für eine erbende Klasse. Ich kann in Form1.vb nicht schreiben: TC2._protected. Ich kann aber die Prozedur inkrementieren() aufrufen, welche _protected ausgibt. Aber dann kann ich ja doch wieder auf sie zugreifen. Kann jemand erklären, wozu das gut ist?

    1.2) Friend bedeutet, die Variable ist innerhalb des Projektes zugreifbar, aber nicht projekt- / assemblyübergreifend. Was bedeutet das? Ich weiß aus der C++-Welt, wenn die Klasse TestClass private wäre (was in vb nicht geht), könnte Form1.vb das trotzdem sehen. Aber wieso das Wort assemblyübergreifend?


    1.3) Man hat mir hier im Forum einst gesagt, dass es Private Protected gäbe. Allerdings bietet mir Visual Studio das nicht an. Ist das so richtig?

    1.4) Hat jemand bitte ein konkretes Anwendungsbeispiel (vielleicht aus dem Leben), wofür man Protected Friend benötigt?

    Hier der Code zu den Fragen 1.1 bis 1.4

    VB.NET-Quellcode

    1. Public Class FormMain
    2. Private TC As New TestClass
    3. Private TC2 As New TestClass2
    4. Private Sub FormMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    5. End Sub
    6. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    7. TC2.inkrementieren()
    8. End Sub
    9. End Class

    und

    VB.NET-Quellcode

    1. Imports Microsoft.VisualBasic.ControlChars
    2. Public Class TestClass
    3. Private eins As Integer = 1 'nicht aus FormMain sichtbar
    4. Public zwei As Integer = 2 'aus FormMain sichtbar
    5. Protected _protected As Integer = 3 'nicht sichtbar, außer für erbende Klasse. Ich kann in Form1.vb nicht schreiben: TC2._protected. Ich kann aber die Prozedur inkrementieren() aufrufen, welche _protected ausgibt.
    6. Friend vier As Integer = 4 'aus FormMain sichtbar, jedoch nicht projektübergreifend?
    7. Protected Friend fuenf As Integer = 5 'Beispiel
    8. End Class
    9. Public Class TestClass2 : Inherits TestClass
    10. Public Sub inkrementieren()
    11. _protected += 1
    12. MessageBox.Show($"Variable '_protected' kann sowohl gelesen als auch bearbeitet werden.{NewLine}{_protected}", "funktioniert", MessageBoxButtons.OK, MessageBoxIcon.Information)
    13. End Sub
    14. End Class


    2.) Vererbung

    Hiermit komme ich soweit klar. Angenommen, eine Sache A ist so allgemein, dass man darauf aufbauen bzw ableiten muss. Zum Beispiel sagt „Ich spiele ein Instrument“ viel zu wenig aus. Man muss von der Klasse Instrument erben und kann dann ein Piano oder Akkordeon erzeugen. Grüße gehen raus an CodeBeauty :) .
    Oder das Beispiel, was wir hier schon hatten:
    Lebewesen ist viel zu allgemein. Ich baue daher eine Systematik auf: Lebewesen SäugetierePaarhuferEchte SchweineHausschwein. Wobei ich natürlich auch die Klasse Paarhufer hernehmen kann, um daraus ein Kamel zu machen.
    Und jede erbende Klasse bringt dann weitere Eigenschaften mit sich.

    Aufgrunddessen, dass vererbt und geerbt werden muss, muss es eine zu überschreibende Prozedur geben, wenn man zum Beispiel den Namen haben will. Wenn man es so ausdrücken möchte: Lebewesen ist sooo allgemein, dass man nicht nach Lebewesen.Name fragen darf. Daher nennt man das pure-virtual. Habe ich das unten richtig gemacht? (Wenn man allerdings ein Beispiel hat, wo es doch genehmigt ist, kann man Overridable schreiben, so dass man sich es aussuchen kann, ob man das möchte oder nicht)

    Die Klassen, die MustInherit im Kopf stehen haben, nennt man dann abstrakt.


    Class Lebewesen

    VB.NET-Quellcode

    1. Public MustInherit Class Lebewesen
    2. Public Alter As Integer
    3. Public Name As String = ""
    4. Public MustOverride Sub Nenne_deinen_Namen() ' pure-virtual gewollt
    5. End Class
    6. Public MustInherit Class Saeugetiere : Inherits Lebewesen
    7. Public kann_fliegen As Boolean
    8. Public Felllaenge As Single 'in Prozent des Möglichen
    9. Public Anzahl_der_Zaehne As Integer
    10. Public Koerpertemperatur As Integer 'in °C
    11. End Class
    12. Public MustInherit Class Paarhufer : Inherits Saeugetiere
    13. Public ist_nachtaktiv As Boolean
    14. Public Structure Waffenarten
    15. Public Property hat_Hoerner As Boolean
    16. Public Property hat_Stosszaehne As Boolean
    17. Public Property hat_Klauen As Boolean
    18. End Structure
    19. End Class
    20. Public MustInherit Class Echte_Schweine : Inherits Paarhufer
    21. Public hat_Bart As Boolean
    22. End Class
    23. Public Class Hausschwein : Inherits Echte_Schweine
    24. Public dieses_wird_im_Stall_gehalten As Boolean
    25. Public WA As Waffenarten 'Instanz erzeugen
    26. Public Sub New(ByVal uebergebenesAlter As Integer, ByVal imStall As Boolean, ByVal Name As String)
    27. Me.Alter = uebergebenesAlter
    28. Me.kann_fliegen = False
    29. Me.Felllaenge = 0.2F
    30. Me.Anzahl_der_Zaehne = 44
    31. Me.Koerpertemperatur = 39
    32. Me.ist_nachtaktiv = False
    33. Me.dieses_wird_im_Stall_gehalten = imStall
    34. Me.WA.hat_Hoerner = False
    35. Me.WA.hat_Stosszaehne = False
    36. Me.WA.hat_Klauen = False
    37. Me.hat_Bart = False
    38. Me.Name = Name
    39. End Sub
    40. Public Overrides Sub Nenne_deinen_Namen()
    41. MessageBox.Show($"{Name} is its name.", "Info", MessageBoxButtons.OK, MessageBoxIcon.Information)
    42. End Sub
    43. End Class


    in Form1.vb

    VB.NET-Quellcode

    1. Private Sub Button_Lebewesen_Click(sender As Object, e As EventArgs) Handles Button_Lebewesen.Click
    2. Dim S1 As New Hausschwein(10, False, "Horst")
    3. S1.Nenne_deinen_Namen()
    4. End Sub

    Bartosz schrieb:

    Friend
    Wenn Du mehrere Projekte in einer Projektmappe hast, können auf mit Friend deklarierte Objekte nur innerhalb der deklarierenden Assembly zugegriffen werden.
    Assembly übergreifend bedeutet, dass Du auf ein Objekt in einer anderen Assembly zugreifst, z.B. auf die Klasse Form.
    Private Protected macht keinen Sinn.
    Private Objekte werden nur innerhakb der Klasse gesehen, Protected Objekte innerehalb abgeleiteter Klassen Assembly übergreifend.
    Protected Friend Objekte innerehalb abgeleiteter Klassen innerhalb einer Assembly.
    Die Verwendung von Protected Friend Klassen ist dann sinnvoll, wenn auf Objekte zugegriffen wird, die von außen nicht gesehen werden sollen oder auf die von außen nicht zugegriffen werden kann, z.B. separate DLLs.
    MustInherit in VB.NEZ ist abstract in C#; C++ weiß ich jetzt nicht genau, wird aber so sein.

    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!
    @Bartosz Du kannst C++- und VB.NET-Zugriffs-Modifikatoren vom Namen her nicht miteinander vergleichen!
    Bestenfalls C / C++ / C# untereinander.
    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!
    Ok, gut zu wissen.

    Und zu
    Protected Friend: Ich verstehe das so: Entweder a) abgleitete Klassen oder b) dasselbe Assembly oder c) beides
    können auf die Variable zugreifen. Das wird bei libraries oder DLLs gemacht.

    Könnte mir noch jemand sagen, ob im Code zum Thema Vererbung ich es richtig gemacht habe, wenn ich pure-virtual will? (Zeile 4)

    @Bartosz Sowohl als auch, AndAlso, nicht OrElse:
    Sowohl abgeleitete Klassen als auch dasselbe Assembly.
    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!

    Bartosz schrieb:

    Dann ist das das, was in C++ Friend heißt ...
    Nö.
    Soweit mir noch in Erinnerung ist, wurde in C++ mit Friend der Zugriff in der Exe/DLL (äquivalent zu Assembly) gestattet.
    Protected heißt und bedeutet überall Protected.
    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!
    Ok, danke. :)

    Form1.vb kann nicht auf die Variable _protected zugreifen. Aber ich kann in der Instanz der TestClass2 eine Sub aufrufen, welche für mich _protected ausliest. Also à la „Ich muss jemand anderen um Erlaubnis bitten“.

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

    @Bartosz Mach Dir etwa so eine Property:

    VB.NET-Quellcode

    1. Private _Test As Integer
    2. Public Property Test() As Integer
    3. Get
    4. Return _Test
    5. End Get
    6. Protected Set(value As Integer)
    7. _Test = value
    8. End Set
    9. End Property
    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!

    Bartosz schrieb:

    aber nur einer kanns verändern.
    Das wäre dann mit nem Private Set.
    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!
    Meinst du das? Bei Exists steht Public Overrides ReadOnly Property Exists as Boolean

    @Gonger96 Habe mir dieses Video rausgesucht. Ich habe es 2018 gesehen, als es herauskam, und habe mich heute etwas falsch erinnert und kam daher durcheinander. Habe an der richtigen Stelle die URL kopiert.
    https://youtu.be/NfFSxZiOP1c


    Bilder
    • Objektkatalog.jpg

      268,52 kB, 1.320×919, 80 mal angesehen
    Ja, das meinte ich.
    Aber warum machst du den OB nicht richtig auf - sodass man die Namespaces und den ganzen Kram auch sieht?
    VisualStudio richtig nutzen (Google ist nicht deine Mami)

    Da wirds einem sehr klar, dass genau das zutrifft:

    Bartosz schrieb:

    Alle können lesen, aber nur die Basisklasse und die abgeleitete Klassen können die Variable verändern. Super!

    Und auf paar andere FileInfo-Member trifft das auch zu, und auf andere wieder nicht.
    Also ich finde diese kleine Klassen-Gruppe: File-/FileSystem-/Directory-/Drive-Info, ich finde das gelungenes KlassenDesign, und man sieht, wie Dinge zusammengefasst werden, die zusammengehören, und unterschieden, wsa unterschiedlich ist, ohne dass Redundanz entsteht.
    Dank der Vererbungs-Logik mit ihre Scopes und Modifier und Kram.

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

    man kann iwie ein klassendiagramm erstellen - ich hab nich nicht rausgefunden, was das bringen soll.

    Aber du kannst dein eigenes Projekt im OB angugge - das ist insbesondere bei typisierten Datasets sehr nützlich.



    Von Diagrammen bin ich ansonsten ziemlich unbeeindruckt (Ausser ER-Diagramm für Datenmodelle).

    Da haste den Bildschirm schnell voll mit viele Kästchen, Kringel und Pfeile, und dann musste erst noch studieren, was die dicken Linien bedeuten im gegensatz zu den dünnen, und was eine Raute, Rechteck oder eines mit runden Ecken...

    Wie gesagt: Der Bildschirm ist voll, und worauf du guckst, ist am Ende nur die Diagramm-Darstellung von etwas, was mit 100 Zeilen gecodet wurde.
    Da guck ich lieber in'n Code.