views:

87

answers:

4

I have a copy function that I'd like to override in subclasses to return the type of the subclass. Here are my interfaces:

Public Interface IBase(Of T)
    Function Copy() As T
End Interface

Public Interface ICar
    Inherits IBase(Of ICar)
End Interface

Public Interface IToyota
    Inherits ICar
End Interface

And here are my classes. As you can see, when Car overrides Copy it return ICar which is what I want. But when Toyota overrides Copy it also wants to return ICar instead of IToyota. How do I write it to return IToyota?

Public MustInherit Class Base(Of T)
    Implements IBase(Of T)

    Protected MustOverride Function Copy() As T Implements IBase(Of T).Copy

End Class

Public Class Car
    Inherits Base(Of ICar)
    Implements ICar

    Protected Overrides Function Copy() As ICar
     Return Nothing //'TODO: Implement Copy
    End Function
End Class

Public Class Toyota
    Inherits Car
    Implements IToyota

    Protected Overrides Function Copy() As IToyota Implements IToyota.Copy
     //'I want this to return IToyota, but gives me a compile error
    End Function

End Class
A: 

Take out the overrides keyword

NOTE: the interface can't implement the function -- you will have to implement it right there. An interface only "defines" that the function will exist.

Hogan
A: 

You cannot override something and return a more specific object. If you want to do that, you will need to use the Shadows keyword, but then it will only return IToyota in the case that you have an actual Toyota variable, not if your variable is of type Car but contains a Toyota object. For example:

Dim MyToyotaVariable as Toyota = New Toyota
MyToyotaVariable.Copy() 'Returns IToyota

Dim MyToyotaVariable as Car = New Toyota
MyToyotaVariable.Copy() 'Returns ICar

That is a limitation of hiding the method in the base class, but the only way you can return a more specific object in a derived class, using the same method name.

Rick Mogstad
+2  A: 

You can't change the return type of a method when you override it. You could omit the overrides keyword to shadow it instead, but then it's of course not virtual any more.

That is not a big problem, unless you try to use an ICar reference to copy a Toyota object to a Toyota reference:

Dim a As IToyota = New Toyota()
Dim b As IToyota = a.Copy() ' works

Dim c As ICar = New Toyota()
Dim d As IToyota = c.Copy() ' doesn't work
Guffa
A: 

You can make your ICar interface more generic, apologies if my vb.net code is not up to scratch.

Public Interface IBase(Of T)    
    Function Copy() As T
End Interface

Public Interface ICar(Of T)    
    Inherits IBase(Of T)
End Interface

Public Interface IToyota    
    Inherits ICar(Of IToyota)
End Interface
Richard Friend