Benutzer mit den meisten Antworten
Probleme bei Eingenschaftzugriff in vererbten Klassen

Frage
-
Hallo,
ich habe eine Basisklasse, die in weitere Klassen vererbt wird. Die Basisklasse besitzt eine Eigenschaft "Parent" als Objekt, das in den anderen Klassen durch die exakte Klassenzuordnung überschrieben wird. Nach dem Überschreiben wird Parent nicht mehr in der Basisklasse erkannt. Wenn ich die Zeile "Public Shadows Parent As clsKlasse2" ausblende funktioniert alles. Wieso ist in der Basisklasse die Parent-Eigenschaft nicht mehr vorhanden? Die Namensabfage in der clsKlasse1 funktioniert.
Public Class Form1 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim obj1 = New clsKlasse1 : Dim obj2 = New clsKlasse2 obj1.Parent = obj2 obj1.ZeigeName() End Sub End Class Public Class clsBasis Public Name As String = "" : Public Parent As Object = Nothing Public Sub ZeigeName() If TypeOf Me Is clsKlasse1 Then MsgBox("Me Is clsKlasse1") MsgBox(Me.Parent.name) End Sub End Class Public Class clsKlasse1 : Inherits clsBasis Public Sub New() Me.Name = "clsKlasse1" End Sub Public Shadows Parent As clsKlasse2 End Class Public Class clsKlasse2 : Inherits clsBasis Public Sub New() Me.Name = "clsKlasse2" End Sub End Class
Peter
Antworten
-
Falls der Shadows benötigt wird so ginge das in etwa so:
Public Class clsKlasse1
Inherits clsBasis
Private mobjParent As clsKlasse2
Public Shadows Property Parent As clsKlasse2
Get
Return mobjParent
End Get
Set(ByVal pValue As clsKlasse2)
mobjParent = pValue
MyBase.Parent = mobjParent
End Set
End Property
Public Sub New()
Me.Name = "clsKlasse1"
End Sub
End Class
- Als Antwort vorgeschlagen Dennis Becker Dienstag, 3. Juli 2012 13:26
- Als Antwort markiert Robert BreitenhoferModerator Donnerstag, 26. Juli 2012 10:10
Alle Antworten
-
Hallo Peter,
wegen des Shadows ist die Parent Variable in der Basisinstanz Nothing.
Der Shadows versteckt das Parent Property von clsBasis für die Objekte von clsKlasse1. Der Button1_Click setzt nur die Parentvariable von objKlasse1 und die Parentvariable von clsBasis bleibt auf Nothing.
Daher erzeugt ZeigeName eine Ausnahme.Brauchst du denn den Public Shadows Parent As clsKlasse2
in clsKlasse1 wirklich? (Dann als Property definieren welches im Property Set MyBase.Parent setzt.)Du könntest Parent in clsBasis als clsBasis definieren.
Würde auch in den Projekteigenschaften Option Strict on stets empfehlen. Dies hilft Fehler zu vermeiden.
Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim obj1 = New clsKlasse1
Dim obj2 = New clsKlasse2
obj1.Parent = obj2
obj1.ZeigeName()
End Sub
End Class
Public Class clsBasis
Public Name As String = ""
Public Parent As clsBasis = Nothing
Public Sub ZeigeName()
If TypeOf Me Is clsKlasse1 Then MsgBox("Me Is clsKlasse1")
MsgBox(Me.Parent.Name)
End Sub
End Class
Public Class clsKlasse1
Inherits clsBasis
Public Sub New()
Me.Name = "clsKlasse1"
End Sub
End Class
Public Class clsKlasse2
Inherits clsBasis
Public Sub New()
Me.Name = "clsKlasse2"
End Sub
End Class
- Bearbeitet Markus222 Montag, 2. Juli 2012 08:03
-
Falls der Shadows benötigt wird so ginge das in etwa so:
Public Class clsKlasse1
Inherits clsBasis
Private mobjParent As clsKlasse2
Public Shadows Property Parent As clsKlasse2
Get
Return mobjParent
End Get
Set(ByVal pValue As clsKlasse2)
mobjParent = pValue
MyBase.Parent = mobjParent
End Set
End Property
Public Sub New()
Me.Name = "clsKlasse1"
End Sub
End Class
- Als Antwort vorgeschlagen Dennis Becker Dienstag, 3. Juli 2012 13:26
- Als Antwort markiert Robert BreitenhoferModerator Donnerstag, 26. Juli 2012 10:10
-
Hier noch mit Compile Options Option Strict On. Ohne Shadows.
Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim obj1 = New clsKlasse1
Dim obj2 = New clsKlasse2
obj1.Parent = obj2
obj1.ZeigeName()
End Sub
End Class
Public Class clsBasis
Public Name As String = ""
Public Parent_Basis As clsBasis = Nothing
Public Sub ZeigeName()
If TypeOf Me Is clsKlasse1 Then MsgBox("Me Is clsKlasse1")
MsgBox(Me.Parent_Basis.Name)
End Sub
End Class
Public Class clsKlasse1
Inherits clsBasis
Private mobjParent As clsKlasse2
Public Property Parent As clsKlasse2
Get
Return mobjParent
End Get
Set(ByVal pValue As clsKlasse2)
mobjParent = pValue
MyBase.Parent_Basis = mobjParent
End Set
End Property
Public Sub New()
Me.Name = "clsKlasse1"
End Sub
End Class
Public Class clsKlasse2
Inherits clsBasis
Public Sub New()
Me.Name = "clsKlasse2"
End Sub
End Class- Bearbeitet Markus222 Sonntag, 1. Juli 2012 21:54
-
Entschuldige. Das ist vermutlich viel zu viel Code. Ich programmiere eigentlich seit 2 Jahren nicht mehr. Ausser dem Sperrprogramm was ich wirklich schreiben müsste nur ab und zu mal eine Antwort. So wie andere halt als Entspannung ab und zu ein Kreuzworträtsel ausfüllen.
Wenn man es nicht regelmässig tut kommt man raus. Man müsste wieder anfangen.
So wie ich es sehe geht es darum dass es eine Basisklasse gibt. In diese verlagerst du Aufgaben von abgeleiteten Klassen damit sie nicht redundant programmiert zu werden brauchen. Dies erleichtert Änderungen und verringert die Codemenge.
Wir haben jetzt mehrere Datentypen. Die Basisklasse und die abgeleiteten Klassen.
Nun möchtest du in einer abgeleiteten Klasse vielleicht Properties und Methoden ansprechen die vom Typ her in der Basisklasse nicht so definiert sind. Die Basisklasse bietet aber diesen Typ nicht. Es gibt ja mehrere abgeleitete Klassen. (clsKlasse1, clsKlasse2....)
Da besteht die Gefahr von redundanten Deklarationen. Halte das für eine Fehlerquelle. Im letzten Beispiel oben ist das auch...
Daher noch einmal ein Beispiel in dem die Parentobjektvariable wirklich nur einmal in der Basisklasse deklariert ist und in der abgeleiteten Klasse darauf zugegriffen und so auf eine doppelte Deklaration verzichtet wird.Es geht bestimmt eleganter. Vielleicht hat ja jemand eine Idee. Denke mal es ist eine Grundfrage der obektorientierten Programmierung. Objektorientierte Programmierung wird heute wohl wieder langsam vergessen... Ebenso wie die Generics in Vebindung damit.
Man will schnelle Lösungen mit Werkzeugen die Hype sind. Man kommt wieder dazu mit der Zeit desto mehr unwartbaren Code zu haben je mehr dieser wächst. Man geht so in die alten Fehler zurück. Man lässt sich blenden von der Aktualität die schnell wechselt.
Mein grösster Wunsch wäre:
Anstatt das Microsoft für ständig neue Technologien immer neue Werkzeuge entwickelt, das wird so weitergehen, sollte es eher dafür sogen dass die vorhandenen Programmierwerkzeuge dafür tauglich sind, d.h. darauf funktionieren.Das hiesse das die Begriffe von Visual Basic eine viel höhere Abstraktionsgröße bedeuten.
Viel Aufwand für Microsoft. Der sich lohnen könnte. Weil vorhandener funktionierender Code Wert bleibt. Es ist einmal Aufwand von Microsoft gegenüber dem millionenfach vervielfachtem Aufwand des immer wieder neu schreiben müssens des immer Gleichen Konzepts um "mithalten" zu können. Bei immer schlechterer Qualität und immer magerer wirklicher innerer Funktionalität weil die Zyklen immer kürzer und der Druck immer grösser wird.Änderung vom 02.07.2012 um 10:20:
Das untere ist dann gefährlich wenn Parent_Basis Public ist. Nur solange es Protected ist kann sich clsKlasse2 darauf verlassen das Parent_Basis vom Typ clsKlasse2 ist.
Ansonsten kann bei Verwendung einer clsBasis Variable die ein Objektzeiger auf eine Instanz von clsKlasse1 ist über den Public Zugriff auf Parent dieses Property auch auf clsKlasse2 gesetzt worden sein.
Um typsicher sich sein müsste Parent also in der abgeleiten Klasse als Objektvariable mit Dim oder Private deklariert sein und die Basisklasse diesen Zeiger bekommen. (Das wäre ein MustInherit ReadOnly Property Parent_Basis in clsBasis welches in clsKlasse1 dann den Wert der lokalen objParent Variable mit Return zurückliefert. D.h. das es für Parent keine Variablendeklaration in clsBasis gibt.)
Oder Parent_Basis bekommt einen Public ReadOnly Property Get und einen Protected WriteOnly Property Set. Wobei die Variablendeklaration selbst Private ist.
Public Class Form1Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim obj1 = New clsKlasse1
Dim obj2 = New clsKlasse2
obj1.Parent = obj2
obj1.ZeigeName()
MsgBox(obj1.Parent.Test)
End Sub
End Class
Public Class clsBasis
Public Name As String = ""Protected Parent_Basis As clsBasis = Nothing
' Falls es notwendig ist auch Public.
' Public Parent_Basis As clsBasis = Nothing
Public Sub ZeigeName()
If TypeOf Me Is clsKlasse1 Then MsgBox("Me Is clsKlasse1")
MsgBox(Me.Parent_Basis.Name)
End Sub
End Class
Public Class clsKlasse1
Inherits clsBasis
Public Property Parent As clsKlasse2
Get
Return DirectCast(Parent_Basis, clsKlasse2)
End Get
Set(ByVal pValue As clsKlasse2)
MyBase.Parent_Basis = pValue
End Set
End Property
Public Sub New()
Me.Name = "clsKlasse1"
End Sub
End Class
Public Class clsKlasse2
Inherits clsBasis
Public Test As String = "Guck Guck"
Public Sub New()
Me.Name = "clsKlasse2"
End Sub
End Class
- Bearbeitet Markus222 Montag, 2. Juli 2012 08:56
-
So und mit Vererbung und Generics kombiniert sähe es dann ungefähr so aus.
Denke das sollte der eigentliche Weg sein und das obige könnte eigentlich gelöscht werden. Aber das oben ist eben auch eine Möglichkeit.
Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim obj1 = New clsKlasse1
Dim obj2 = New clsKlasse2
obj1.Parent = obj2
obj1.ZeigeName()
MsgBox(obj1.Parent.Test)
End Sub
End Class
Public MustInherit Class clsBasis
Public Name As String = ""
End Class
Public MustInherit Class clsBasis_Derived(Of clsParent_TP As clsBasis)
Inherits clsBasis
Public Parent As clsParent_TP
Public Sub ZeigeName()
If Me.GetType Is GetType(clsKlasse1) Then MsgBox("Me Is clsKlasse1")
MsgBox(Me.Parent.Name)
End Sub
End Class
Public Class clsKlasse1
Inherits clsBasis_Derived(Of clsKlasse2)
Public Sub New()
Me.Name = "clsKlasse1"
End Sub
End Class
Public Class clsKlasse2
Inherits clsBasis
Public Test As String = "Guck Guck"
Public Sub New()
Me.Name = "clsKlasse2"
End Sub
End Class- Bearbeitet Markus222 Montag, 2. Juli 2012 07:54
-
Vielen Dank,
der entscheidende Hinweis war die Zeile MyBase.Parent = pValue in der Eigenschaft der Klasse1 (2. Beitrag von Markus). Die Private Parent Variable benötigt man nur in der Basisklasse, die Parent-Eigenschaft in der abgeleiteten ist Shadow und alles funktioniert wunderbar.
Auch der Hinweis StrictOn war gut. Das ist wohl guter Programmierstil, den ich verinnerlichen sollte.
Merci Peter
Peter