Basisklasse, eine Property kann nicht überschrieben werden EDIT: Allgemeinte Fragen zu Basisklassen und Interfaces

  • VB.NET
  • .NET (FX) 4.0

Es gibt 49 Antworten in diesem Thema. Der letzte Beitrag () ist von sonne75.

    Basisklasse, eine Property kann nicht überschrieben werden EDIT: Allgemeinte Fragen zu Basisklassen und Interfaces

    Hallo,

    ich weiß, der Titel ist etwas ungenau, aber ich wusste nicht, wie ich das auf Anhieb besser formuliere.

    Ich versuche mich gerade an abstrakten Basisklassen und scheitere gerade an einer Property. Ich habe eine Basisklasse ChannelData, von der 3 Klassen erben, jede von ihnen hat eine Property vom Typ XXChannelRow (eine typisierte Row). Ich dachte, wenn ich in der Basisklasse eine Overridable Property vom Type DataRow deklariere, kann ich sie in den abgeleiteten Klassen durch diese Properties überschrieben, da XXChannelRow jeweils von DataRow erbt.
    (steht im Designer-Code):

    VB.NET-Quellcode

    1. Partial Public Class ReceiveChannelRow
    2. Inherits Global.System.Data.DataRow


    Allerdings ist es nicht der Fall, ich bekomme die Fehlermeldung:

    Fehler 4 "Protected Overrides Property _rwChan As dtsSTCModbus.ReceiveChannelRow" kann "Protected Overridable Property _rwChan As System.Data.DataRow" nicht überschreiben, da sie sich durch Rückgabetypen unterscheiden.


    Wie kann ich es noch machen?

    EDIT: das Gleiche in einem Interface... ;(

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

    Du müsstest die Property mit As DataRow deklarieren.
    Zuweisen/Ausgeben kannst du dann ja eh zb deine ReceiveChannelRow.

    VB.NET-Quellcode

    1. Class XY
    2. Inherits Channeldata
    3. Private _DeineDataRow as ReceiveChannelRow
    4. Public Overrides Property TestProp As DataRow
    5. Get
    6. Return _DeineDataRow
    7. End Get
    8. Set(value As DataRow)
    9. _DeineDataRow = value
    10. End Set
    11. End Property
    12. End Class


    Vielleicht noch im Konstruktor als Parameter ein Objekt von ReceiveChannelRow mitübergeben.

    lg
    ScheduleLib 0.0.1.0
    Kleine Lib zum Anlaufen von Code zu bestimmten Zeiten
    Hab es schon bearbeitet. War vom Testprojekt nur mit den Bezeichnungen darin wärst nicht glücklick geworden^^

    In der abstrakten Basisklasse ist eine override Property von Typ DataRow.
    In der abgeleiteten Klasse überschreibst du die Property. Hast aber eine Private Variable von zB Typ ReceiveChannelRow welche den Wert ausgibt und zugewiesen bekommt.

    lg
    ScheduleLib 0.0.1.0
    Kleine Lib zum Anlaufen von Code zu bestimmten Zeiten
    Die Frage ist, warum es mit abgeleiteten Typen nicht geht?

    Bzw. nur als Argumente in einer Methode, nicht aber als Rückgabetyp...

    Wozu brauche ich dann überhaupt diese Klimmzüge?

    Ich dachte, wenn ich im Konstruktor die jeweilige ChannelRow übergebe und meine Property darauf setze, dass sie dann den Typ ändert, aber Pustekuchen :(

    @fichz
    Ich glaube, da ist was faul, denn ich bekomme im Setter:
    Fehler 8 "Option Strict On" lässt keine impliziten Konvertierungen von System.Data.DataRow in dtsSTCModbus.ActuatorChannelRow zu.


    Warum soll er sie konvertieren, wenn sie davon erbt???

    EDIT: auch wenn ich im Konstuktor ActuatorChannelRow übergebe, kann ich auf Member meine Property nicht zugreifen, weil sie sie nicht findet (Member gibt es nur in der abgeleiteten ActuatorChannelRow).

    VB.NET-Quellcode

    1. Private _rwChan As ActuatorChannelRow
    2. Public Property rwChan As DataRow Implements IRegister.rwChan
    3. Get
    4. Return _rwChan
    5. End Get
    6. Set(ByVal value As DataRow)
    7. _rwChan = DirectCast(value, ActuatorChannelRow)
    8. End Set
    9. End Property
    10. Public Sub New(ByVal rwCh As ActuatorChannelRow)
    11. rwChan = rwCh
    12. act_reg_addr = start_act_reg + reg_length * CUShort(rwChan.ChanID - 1) 'hier ist Fehlermeldung, dass ChanID kein Member von DataRow ist




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

    Das liegt generell daran, dass du eine Methode überschreiben willst. Damit ist aber der Inhalt und nicht die Datentypen gemeint.
    Was du versucht ist Überschatten (Shadows). Hiermit könntest du die Datentypen ändern, unterbricht aber die Erbfolge.

    lg
    ScheduleLib 0.0.1.0
    Kleine Lib zum Anlaufen von Code zu bestimmten Zeiten
    Habe jetzt editiert, da ist jetzt Code drin. Ich kann es gar nicht verwenden ;(

    Wozu brauche ich dann überhaupt Interface/abstrakte Basisklassen, wenn ich abgeleitete Typen gar nicht verwenden kann? Ich habe nunmal in jeder Klasse jeweilige Datentypen. Ich dachte, das wäre das Kerstück des Polymorphismus, dass man auch abgeleitete Klassen als Datentyp reinschieben kann.
    Die Fehlermeldung in deinem Konstruktor Snippet ist klar, da deine Property nur Member vom Typ DataRow kennt.

    Hier mal ein simples Beispiel (Consolenanwendung):

    VB.NET-Quellcode

    1. Module Module1
    2. Sub Main()
    3. Dim c1 As BasisClass = New SubClass1()
    4. c1.Text()
    5. Dim c2 As BasisClass = New SubClass2()
    6. c2.Text()
    7. Console.ReadLine()
    8. End Sub
    9. End Module
    10. Public Class BasisClass
    11. Public Overridable Sub Text()
    12. Console.WriteLine("BasisKlasse")
    13. End Sub
    14. End Class
    15. Public Class SubClass1
    16. Inherits BasisClass
    17. Public Overrides Sub Text()
    18. MyBase.Text()
    19. Console.WriteLine("SubClass1")
    20. End Sub
    21. End Class
    22. Public Class SubClass2
    23. Inherits BasisClass
    24. Public Property Zahl As Integer = 2
    25. Public Overrides Sub Text()
    26. MyBase.Text()
    27. Console.WriteLine("SubClass2 + Zahl " & Zahl.ToString())
    28. End Sub
    29. End Class


    Beide Klassen überschreiben die Methode Text. Beide führen den Code der Basisklasse aus und jeweils seinen eigenen (der durch Polymorphismus jeweils anders aussieht).
    Bei einem IO.Stream ist im Prinzip nichts anderes. FileStream oder NetworkStream funktionieren im Prinzip auch nicht anders. Beide Subklassen empfangen ihre Daten von woanders. Einmal von einer Datei und die andere von einem Netzwerk. Beide bereiten die Daten aber in ihrer abgeleiteten Funktion so auf, dass der normale IO.Stream damit was anfangen kann. Somit kann ich einer Funktion welche einen IO.Stream haben will, auch einen Network-Stream als Parameter übergeben und es funktioniert wie gewünscht.

    Ist irgendwie etwas schwer zu erklären das Ganze finde ich :/

    lg
    ScheduleLib 0.0.1.0
    Kleine Lib zum Anlaufen von Code zu bestimmten Zeiten
    Das ist aber alles was Anderes, als ich will. Dass man Methoden überschreiben kann, hat ja nichts mit meinem Problem der abgeleiteten Typen zu tun.

    Hier:
    msdn.microsoft.com/de-de/library/akfttx8c(v=vs.90).aspx

    steht
    In diesem Beispiel akzeptiert die ShowTax-Prozedur den Parameter Item des Typs BaseTax; Sie können aber auch eine andere, von der BaseTax-Klasse abgeleitete Klasse übergeben, z. B. CityTax. Der Vorteil dieses Entwurfs liegt darin, dass Sie von der BaseTax-Klasse abgeleitete neue Klassen hinzufügen können, ohne den Clientcode in der ShowTax-Prozedur zu ändern.


    Mir geht es ja um "auf Vererbung basierten Polymorphismus" und er funktioniert anscheinend nur mit Übergabeparametern und nicht mit Rückgabetypen.

    Ich habe jetzt die Propertys aus Interface und Baseklasse einfach rausgeschmissen.
    Aber meine Klasse hat nichts mit DataRow zu tun... Sinngemäß. Sie greift nur auf eine DataRow zu, unter anderem, macht aber noch viel mehr.

    Scheitert aber auch am Konstruktor, den ich unbegingt hinzufügen muss (laut IDE) und der irgendeinen "builder" braucht...

    @us4711
    Ist aber das Gleiche: unterschiedliche Rückgabetypen, geht nicht (overrides geht nicht)

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

    @sonne75

    Isses dann vielleicht sowas?

    VB.NET-Quellcode

    1. Public MustInherit Class ChannelData
    2. MustOverride Property XXChannelRow As XXChannelDatset.XXChannelRow
    3. End Class
    4. Public Class MyInheritedClass
    5. Inherits ChannelData
    6. Public Overrides Property XXChannelRow As XXChannelDatset.XXChannelRow
    7. End Class
    Das Problem ist ja, dass jeder der drei abgeleiteten Klassen eine andere XXRow hat, sonst bräuchte ich keinen Basistyp. Ich habe 3 Channeltypen, jeder hat eine eigene Tabelle (weil unterschiedliche Eigenschaften und Vorgehensweisen) und somit natürlich unterschiedlichen Datentyp bei XXChannelRow.

    Ich dachte nur, wenn sie alle von DataRow erben, kann ich Polymorphie nutzen, aber das geht bei Rückgabetypen nicht, nur bei Übergabeparameter (wie oben im Zitat von MSDN).
    Hallo Sonne,

    Ich weiss genau, was du meinst. Das Problem liegt darin, dass in der DotNet-Welt Kontravarianz bei den Rückgabetapen von überschreibenden Methoden nicht implementriert wurde. Leider kann man da nichts weiter machen, als beim Aufrufen der Methode den Rückgabetyp zu casten. Ausser du gehst über Generikas. Vielleicht erinnerst du dich daran, dass ich das mal angesprochen habe. Wenn ich mich nachher an den PC setze suche ich noch den Thread heraus, den ich dafür eröffnet habe.

    Grüsse,

    Higlav
    Ah OK.

    Dann sollte das vielleicht gehen:

    VB.NET-Quellcode

    1. Public MustInherit Class ChannelData(Of T)
    2. MustOverride Property XXChannelRow As T
    3. End Class
    4. Public Class MyInheritedClass1
    5. Inherits ChannelData(Of XXChannelDatset.XXChannel1Row)
    6. Public Overrides Property XXChannelRow As XXChannelDatset.XXChannel1Row
    7. End Class
    8. Public Class MyInheritedClass2
    9. Inherits ChannelData(Of XXChannelDatset.XXChannel2Row)
    10. Public Overrides Property XXChannelRow As XXChannelDatset.XXChannel2Row
    11. End Class
    Mir geht es eigentlich nur über die Propertys, weil jeder Channeltyp eine DataRow des jeweiligen Types haben muss, deswegen wollte ich es vorschreiben.
    Du meinst, ich sollte sie im Konstruktor dann casten? Das probiere ich noch aus. Ich müsste dann eine Zwischenvariable anlegen, als DataRow, und sie dann in XXChannelRow casten und meiner Property (die als DataRow gekennzeichnet ist) zu weisen und dann müsste ich auf die Eigenschaften der XXChannelRow zugreifen können.

    @us4711
    Das ist natürlich auch nicht schlecht...
    Habe gerade meinen Thread gefunden. Dort hat mir Artentus die gleiceh Lösung genannt. :thumbup:
    Aber woran sollten die Events denn deiner Meinung nach scheitern?
    Mach mal so:

    VB.NET-Quellcode

    1. Public MustInherit Class ChannelData(Of T)
    2. MustOverride Property XXChannelRow As T
    3. Public Event ChanellEvent(sender As Object, e As ChannelEventArguments(Of T))
    4. Public Sub UseEvent(_Description As String, _TypedDataRow As T)
    5. RaiseEvent ChanellEvent(Me, New ChannelEventArguments(Of T)(_Description, _TypedDataRow))
    6. End Sub
    7. End Class
    8. Public Class MyInheritedClass1
    9. Inherits ChannelData(Of XXChannelDatset.XXChannel1Row)
    10. Public Overrides Property XXChannelRow As XXChannelDatset.XXChannel1Row
    11. Sub DoEvent()
    12. Me.UseEvent("GandalfUndElbenstein", XXChannelRow)
    13. End Sub
    14. End Class
    15. Public Class MyInheritedClass2
    16. Inherits ChannelData(Of XXChannelDatset.XXChannel2Row)
    17. Public Overrides Property XXChannelRow As XXChannelDatset.XXChannel2Row
    18. Sub DoEvent()
    19. Me.UseEvent("FrodoUndBilbo", XXChannelRow)
    20. End Sub
    21. End Class
    22. Public Class ChannelEventArguments(Of t)
    23. Inherits EventArgs
    24. Public Sub New(_description As String, _TypedDataRow As t)
    25. Me.Description = _description
    26. Me.TypedDataRow = _TypedDataRow
    27. End Sub
    28. Property Description As String
    29. Property TypedDataRow As t
    30. End Class


    //Edit: Ein paar Typos in Zeilen 19 und 20 überarbeitet.

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