2010-05-07 4 views
6

Betrachten Sie die folgenden Klassen repräsentiert ein Bestellsystem:Ist es möglich, eine Eigenschaft zu überschreiben und einen abgeleiteten Typ in VB.NET zurückzugeben?

Public Class OrderBase 
    Public MustOverride Property OrderItem as OrderItemBase 
End Class 

Public Class OrderItemBase 
End Class 

Nun nehmen wir an, diese Klassen zu einem bestimmten Satz von Auftragsklassen, halten die Summe der Natur von Orderbase erweitern möchten:

Public Class WebOrder 
    Inherits OrderBase   

    Public Overrides Property OrderItem as WebOrderItem 
    End Property 
End Class 

Public Class WebOrderItem 
    Inherits OrderItemBase 
End Class 

Die Overriden-Eigenschaft in der WebOrder-Klasse verursacht einen Fehler, der besagt, dass sich der Rückgabetyp von dem in OrderBase definierten unterscheidet. Der Rückgabetyp ist jedoch eine Unterklasse des in OrderBase definierten Typs. Warum lässt VB das nicht zu?

+0

Definieren Sie Ihre Bestellung Artikel als Array ist eine schlechte Idee sowieso. Verwenden Sie eine Liste oder ein Ienumerable. –

+0

In meinem echten Code sind sie Listen. Entschuldigung für die Verwirrung mit dem(). –

+1

Siehe auch die Antworten auf [diese C# -Frage] (http://stackoverflow.com/questions/157119/c-sharp-can-o-override-with-derived-types) aus Gründen und Tricks/Workarounds. ([C# s Method Signatur "neu" ist "Schatten" in VB.Net]) (http://stackoverflow.com/questions/8575418/difference-between-shadows-vb-net-and-new-c)) –

Antwort

7

Sie können das nicht tun - es ändert die Signatur, die auf der Basis definiert ist. Zu tun, was Sie versuchen, was Sie tun müssen Generika verwenden:

Public Class OrderBase(Of T As IOrderItem) 
    Public ReadOnly Property OrderItems As IList(Of T) 
End Class 

My Visual Basic rostig ist so hoffnungsvoll, dass genau ...

+0

Ihre Syntax war in Ordnung, aber wenn Sie zu generic gehen, haben Sie eine Sache übersehen: Sie müssen die Eigenschaft nicht mehr überschreiben - die Basisimplementierung ist bereits korrekt. Außerdem werden wir wahrscheinlich eine Schnittstelle anstelle einer Basisklasse für die orderItems verwenden können. Ich habe es für dich aufgeräumt. –

+0

Auch - ich habe meinen Kommentar über die Verwendung einer Liste anstelle eines Arrays aufgenommen. Ich mag es nicht, nur umkehren. –

+0

Changed die Eigenschaft zu überschreiben - anders als das, danke für die Formatierung für mich. –

4

Sie können nicht die Unterschrift Ihrer Klasse ändern Sie es auf überschreiben. Sie können jedoch zurückgeben abgeleiteten Typ:

Public Overrides Property OrderItem() as OrderItemBase 
    Get 
     Return New WebOrderItem() 
    End Get 
End Property 

Public Sub Whatever() 
    Dim item As WebOrderItem = DirectCast(OrderItem, WebOrderItem) 
End Sub 

Alternativ, wenn Sie die Typen strenger erzwingen möchten, verwenden Generika mit generischen Typ Einschränkungen, wie unten dargestellt:

Public MustInherit Class OrderBase(Of T As OrderItemBase) 
    Public MustOverride ReadOnly Property OrderItem() As T 
End Class 

Public Class OrderItemBase 
End Class 

Public Class WebOrder(Of T As WebOrderItem) 
    Inherits OrderBase(Of T) 

    Public Overrides ReadOnly Property OrderItem() As T 
     Get 
      Return New WebOrderItem() 
     End Get 
    End Property 
End Class 

Public Class WebOrderItem 
    Inherits OrderItemBase 
End Class 

Oder dies tun wenn Sie nicht wollen, WebOrder auch eine generische Klasse zu sein:

Public Class WebOrder 
    Inherits OrderBase(Of WebOrderItem) 

    Public Overrides ReadOnly Property OrderItem() As WebOrderItem 
     Get 
      Return New WebOrderItem() 
     End Get 
    End Property 
End Class 
+0

Leider wird das nicht jemand z. Halten Sie eine Liste von Objekten, die einige Arten von OrderBase darstellen, rufen Sie OrderItem auf und rufen Sie einige von OrderItemBase abgeleitete Objekte ab. Das könnte man aber mit kovarianten Schnittstellen machen. – supercat

3

ein Ansatz ist eine geschützte überschreibbare Methode zu haben, und haben dann eine öffentliche nicht-überschreibbare Methode, die die ov ruft Fehlanzeige. Jedes Mal, wenn der Rückgabewert für die Funktion in der abgeleiteten Klasse geändert werden soll, muss eine überschreibbare überschreibende Methode der überschreibbaren Methode eine neue überschreibbare Methode aufrufen, die den verfeinerten Typ zurückgibt, und auch die frühere Version der öffentlichen Funktion mit einer schattieren neue Überschreibung Wenn vb.net einer Klasse erlaubt, das selbe Mitglied zu überschreiben und zu überschatten, wären die Dinge viel sauberer, aber es gibt keine Möglichkeit, das zu tun.

Public Class CarFactory 
    Protected Overridable Function DerivedMakeCar() as Car 
    ' make a car 
    End Function 

    Public Function MakeCar() as Car 
    Return DerivedMakeCar() 
    End Function 

End Class 

Public Class FordFactory 
    Inherits CarFactory 

    Protected Overrides Function DerivedMakeCar() As Car 
    Return DerivedMakeFord() 
    End Function 

    Protected Overridable Function DerivedMakeFord() As Ford 
    ' Make a Ford 
    End Function 

    Public Shadows Function MakeCar() As Ford 
    Return DerivedMakeFord() 
    End Function 

End Class 

Eine einfachere Alternative kann in einigen Fällen eine öffentliche overridable MakeCar() Funktion zu haben sein, die immer ein Objekt vom Typ zurückgibt Car, haben aber eine FordFactory auch eine MakeFord() Funktion enthalten, die einen Ford zurückgibt.

Die überschriebene MakeCar() Funktion wäre NotOverridable und würde einfach MakeFord aufrufen. In gewisser Weise kann der letztere Ansatz sauberer sein, aber wenn es eine gemeinsame Namenskonvention gibt (z. B. Fabriken haben eine MakeProduct-Methode, die den am weitesten abgeleiteten Typ zurückgibt), kann es nützlich sein, Schatten zu verwenden.

Verwandte Themen