2010-05-07 18 views
6

Tenir compte des classes suivantes représentant un système de commande:Est-il possible de surcharger une propriété et de renvoyer un type dérivé dans VB.NET?

Public Class OrderBase 
    Public MustOverride Property OrderItem as OrderItemBase 
End Class 

Public Class OrderItemBase 
End Class 

Maintenant, supposons que nous voulons étendre ces classes à un ensemble plus précis des classes d'ordre, en gardant la nature globale des OrderBase:

Public Class WebOrder 
    Inherits OrderBase   

    Public Overrides Property OrderItem as WebOrderItem 
    End Property 
End Class 

Public Class WebOrderItem 
    Inherits OrderItemBase 
End Class 

La propriété Overriden dans la classe WebOrder provoquera une erreur indiquant que le type de retour est différent de celui défini dans OrderBase ... cependant, le type de retour est une sous-classe du type défini dans OrderBase. Pourquoi VB ne le permettra-t-il pas?

+0

Définir vos éléments de commande en tant que tableau est une mauvaise idée de toute façon. Utilisez une liste ou un Ienumerable. –

+0

Dans mon code réel ce sont des listes. Désolé pour la confusion avec le(). –

+1

Voir aussi les réponses à [cette question C#] (http://stackoverflow.com/questions/157119/c-sharp-can-i-override-with-derived-types) pour des raisons et astuces/solutions de contournement. ([La signature de méthode de C# "new" est "Shadows" dans VB.Net] (http://stackoverflow.com/questions/8575418/difference-between-shadows-vb-net-and-new-c)) –

Répondre

7

Vous ne pouvez pas faire cela - c'est changer la signature définie sur la base. Pour faire ce que vous essayez de faire, vous devez utiliser les médicaments génériques:

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

Mon Visual Basic est rouillé si nous espérons que ce soit exact ...

+0

Votre syntaxe était correct, mais en passant au générique, vous avez manqué une chose: vous n'avez plus besoin de surcharger la propriété - l'implémentation de base sera déjà correcte. De plus, maintenant nous serons probablement en mesure d'utiliser une interface plutôt qu'une classe de base pour les orderItems. Je l'ai nettoyé pour toi. –

+0

Aussi - J'ai incorporé mon commentaire sur l'utilisation d'une liste plutôt que d'un tableau. Je vous n'aime pas juste revenir. –

+0

Changé la propriété à overridable - autre que cela, merci pour le formatage pour moi. –

4

Vous ne pouvez pas changer la signature de votre classe à la redéfinir. Vous pouvez cependant retourner un type dérivé:

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 

Alternativement, si vous souhaitez appliquer les types plus strictement, utilisez génériques avec des contraintes de type générique, comme indiqué ci-dessous:

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 

Ou faire si vous ne voulez pas WebOrder être une classe générique ainsi:

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

Malheureusement, cela ne permettra pas à quelqu'un d'ex. contient une liste d'objets qui représentent certains types de OrderBase, appelle OrderItem et récupère des objets dérivés de OrderItemBase. On pourrait le faire avec des interfaces covariantes, cependant. – supercat

3

une approche est d'avoir une méthode Overridable protégée, puis une méthode publique non substituable qui appelle la ov un errant. Chaque fois que la valeur de retour de la fonction dans la classe dérivée doit changer, un override notoverridable de la méthode overridable appelle une nouvelle méthode overridable qui retourne le type plus raffiné, et ombrage également la version antérieure de la fonction publique avec celle qui utilise le nouveau remplacement. Si vb.net permettait à une classe de surcharger et d'ombrer le même membre, les choses seraient beaucoup plus propres, mais il n'y a aucun moyen de le faire.

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 

Une alternative plus simple dans certains cas, peut être d'avoir une fonction publique Overridable MakeCar() qui retourne toujours un objet de type Car, mais un FordFactory inclut également une fonction MakeFord() qui retourne une Ford.

La fonction surchargée MakeCar() serait NotOverridable et appellerait simplement MakeFord. À certains égards, la dernière approche peut être plus propre, mais s'il existe une convention de dénomination commune (par exemple, les usines ont une méthode MakeProduct qui renvoie le type le plus dérivé), il peut être utile d'utiliser Shadows.