2010-05-07 11 views
6

considerar las siguientes clases que representan un sistema de pedidos:¿Es posible anular una propiedad y devolver un tipo derivado en VB.NET?

Public Class OrderBase 
    Public MustOverride Property OrderItem as OrderItemBase 
End Class 

Public Class OrderItemBase 
End Class 

Ahora, supongamos que queremos extender estas clases a un conjunto más específico de clases de orden, manteniendo la naturaleza global de OrderBase:

Public Class WebOrder 
    Inherits OrderBase   

    Public Overrides Property OrderItem as WebOrderItem 
    End Property 
End Class 

Public Class WebOrderItem 
    Inherits OrderItemBase 
End Class 

La propiedad Overriden en la clase WebOrder causará un error que indica que el tipo de devolución es diferente del definido en OrderBase ... sin embargo, el tipo de devolución es una subclase del tipo definido en OrderBase. ¿Por qué VB no lo permite?

+0

Definir los artículos de su pedido como una matriz es una mala idea de todos modos. Use una lista o un Iumerable. –

+0

En mi código real son listas. Perdón por la confusión con el(). –

+1

Consulte también las respuestas a [esta pregunta C#] (http://stackoverflow.com/questions/157119/c-sharp-can-i-override-with-derived-types) por motivos y trucos/soluciones provisionales. ([C# 's método firma "nuevo" es "Sombras" en VB.Net] (http://stackoverflow.com/questions/8575418/difference-between-shadows-vb-net-and-new-c)) –

Respuesta

7

No puede hacer eso, está cambiando la firma definida en la base. Para hacer lo que está tratando de hacer lo necesario para utilizar los genéricos:

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

Mi Visual Basic es oxidado por lo que esperamos que sea precisa ...

+0

Su sintaxis estuvo bien, pero yendo al genérico omitió una cosa: ya no necesita anular la propiedad; la implementación base ya será correcta. Además, ahora es probable que podamos utilizar una interfaz en lugar de una clase base para orderItems. Lo limpié para ti. –

+0

Además, incorporé mi comentario sobre el uso de una lista en lugar de una matriz. No me gusta, solo revierte. –

+0

Cambié la propiedad a invalidable, aparte de eso, gracias por formatearlo para mí. –

4

No se puede cambiar la firma de su clase sobre la anulando la misma. Puede, sin embargo, devolver un tipo derivado:

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 

Alternativamente, si desea aplicar los tipos más estricta, utiliza los genéricos con limitaciones de tipo genérico, como se muestra a continuación:

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 

O hacer esto Si no desea que WebOrder ser una clase genérica, así:

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

Desafortunadamente, eso no permitirá que alguien, p. Ej. mantenga una lista de objetos que representan algunos tipos de OrderBase, llame a OrderItem y obtenga algunos objetos derivados de OrderItemBase. Uno podría hacer eso con interfaces covariantes, sin embargo. – supercat

3

un enfoque es tener un método reemplazable protegido, y luego tener un método no reemplazable público que llama a la OV uno erridable. Cada vez que el valor de retorno de la función en la clase derivada debe cambiar, tener una anulación irrecuperable del método reemplazable llama a un nuevo método invalidable que devuelve el tipo más refinado y también sombrea la versión anterior de la función pública con una que usa el nueva anulación Si vb.net permitiera que una clase anulara y sombreara al mismo miembro, las cosas serían mucho más limpias, pero no hay forma de hacerlo.

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 

Una alternativa más simple en algunos casos puede ser tener una función pública MakeCar reemplazable() que siempre devuelve un objeto de tipo Car, pero tienen un FordFactory incorpora también una función MakeFord() que devuelve un Ford.

La función invalidada de MakeCar() sería NotOverridable y simplemente llamaría a MakeFord. De alguna manera, este último enfoque puede ser más limpio, pero si hay una convención de nomenclatura común (por ejemplo, las fábricas tienen un método MakeProduct que devuelve el tipo más derivado), puede ser útil usar Shadows.

Cuestiones relacionadas