Sunday, February 13, 2011

From Child instance call base class method that was overridden

Consider the following code:

Public Class Animal

Public Overridable Function Speak() As String
    Return "Hello"
End Function

End Class

Public Class Dog
    Inherits Animal

    Public Overrides Function Speak() As String
        Return "Ruff"
    End Function

End Class

Dim dog As New Dog
Dim animal As Animal
animal = CType(dog, Animal)
// Want "Hello", getting "Ruff"
animal.Speak()

How can I convert/ctype the instance of Dog to Animal and have Animal.Speak get called?

  • you don't; the subclass's method overrides the superclass's method, by definition of inheritance

    if you want the overridden method to be available, expose it in the subclass, e.g.

    Public Class Dog 
        Inherits Animal
        Public Overrides Function Speak() As String
            Return "Ruff"
        End Function
        Public Function SpeakAsAnimal() As String
            Return MyBase.Speak()
        End Function
    End Class
    

    (untested)

  • I don't think you can.

    The thing is that the object is still a dog. the behavior you're describing (getting "ruff" from the casted object rather than "hello") is standard because you want to be able to use the animal class to let a bunch of different type of animals speak.

    For example, if you had a third class as thus:

    Public Class Cat
        Inherits Animal
    
        Public Overrides Function Speak() As String
            Return "Meow"
        End Function
    End Class
    

    Then you'd be able to access them like thus:

    protected sub Something
        Dim oCat as New Cat
        Dim oDog as New Dog
    
        MakeSpeak(oCat)
        MakeSpeak(oDog)
    End sub
    
    protected sub MakeSpeak(ani as animal)
        Console.WriteLine(ani.Speak())
    end sub
    

    What you're talking about doing basically breaks the inheritance chain. Now, this can be done, by setting up the Speak function to accept a parameter which tells it to return it's base value or not or a separate SPEAK function for the base value, but out of the box, you're not going to get things that behave this way.

    Mike Deck : "Another alternative, is to declare the object as an ANIMAL, and then cast it to a DOG when you need the dog's extended properties." That last part is not true. The declared type of the variable is meaningless when it comes to how a given instance behaves polymorphically.
    Stephen Wrighton : That's true, I was thinking in terms of interfaces.
  • I would ask why you are trying to get this type of behavior. It seems to me that the fact you need to invoke the parent class' implementation of a method is an indication that you have a design flaw somewhere else in the system.

    Bottom line though, as others have stated there is no way to invoke the parent class' implementation given the way you've structured your classes. Now within the Dog class you could call

    MyBase.Speak()
    

    which would invoke the parent class' implementation, but from outside the Dog class there's no way to do it.

    From Mike Deck
  • I think if you drop "Overridable" and change "Overrides" to "New" you'll get what you want.

    Public Class Animal
    
    Public Function Speak() As String
        Return "Hello"
    End Function
    
    End Class
    
    Public Class Dog
        Inherits Animal
    
        Public New Function Speak() As String
            Return "Ruff"
        End Function
    
    End Class
    
    Dim dog As New Dog
    Dim animal As Animal
    dog.Speak() ' should be "Ruff"
    animal = CType(dog, Animal)
    animal.Speak() ' should be "Hello"
    
    From Matt Burke

0 comments:

Post a Comment