2008-10-28 8 views
7

Consultez le code suivant:méthode de classe de base d'appel d'instance enfant qui a été surchargée

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() 

Comment puis-je convertir/ctype l'instance de chien à des animaux et ont Animal.Speak appelée?

Répondre

10

Vous ne le faites pas; la méthode de la sous-classe remplace la méthode de la superclasse, par définition de l'héritage.

Si vous souhaitez que la méthode substituée soit disponible, exposez-la dans la sous-classe, par ex.

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 
0

Je ne pense pas que vous le pouvez.

Le fait est que l'objet est toujours un chien. le comportement que vous décrivez (obtenir "ruff" de l'objet casted plutôt que "hello") est standard parce que vous voulez être en mesure d'utiliser la classe des animaux pour laisser parler un groupe d'animaux différents.

Par exemple, si vous aviez une troisième classe ainsi:

Public Class Cat 
    Inherits Animal 

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

Ensuite, vous seriez en mesure d'y accéder comme ainsi:

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 

Qu'est-ce que vous parlez essentiellement de faire casse la chaîne d'héritage. Maintenant, cela peut être fait, en configurant la fonction Parler pour accepter un paramètre qui lui demande de retourner sa valeur de base ou non ou une fonction SPEAK séparée pour la valeur de base, mais dans la boîte, vous n'allez pas pour obtenir des choses qui se comportent de cette façon.

+0

« Une autre alternative, est de déclarer l'objet comme un animal, puis jeté à un chien quand vous avez besoin des propriétés étendues du chien " Cette dernière partie n'est pas vraie. Le type déclaré de la variable n'a pas de sens quand il s'agit de la façon dont une instance donnée se comporte polymorphiquement. –

+0

C'est vrai, je pensais en termes d'interfaces. –

1

Je demanderais pourquoi vous essayez d'obtenir ce type de comportement. Il me semble que le fait que vous ayez besoin d'invoquer l'implémentation d'une méthode par la classe parente indique que vous avez un défaut de conception ailleurs dans le système.

La ligne de fond cependant, comme d'autres l'ont indiqué il n'y a aucun moyen d'invoquer l'implémentation de la classe parente étant donné la façon dont vous avez structuré vos classes. Maintenant, dans la classe Dog, vous pouvez appeler

MyBase.Speak() 

qui justifierait la mise en œuvre de la classe mère, mais à l'extérieur de la classe Dog il n'y a pas moyen de le faire.

1

Je pense que si vous supprimez "Overridable" et remplacez "Overrides" par "New", vous obtiendrez ce que vous voulez.

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" 
+2

Le nouveau mot-clé est comment vous le feriez en C#. L'équivalent en VB est Shadows. C'est généralement une mauvaise idée d'utiliser Shadows. C'est une mauvaise pratique de conception orientée objet. C'est une violation du principe de substitution de Liskov. –

0

Je sais que cela a été posté il ya quelques mois, mais je vais encore essayer de répondre, peut-être juste pour l'exhaustivité.

Vous avez été informé que vous pouvez accéder à la méthode substituée de au sein de la classe dog, et que vous pouvez ensuite l'exposer avec un nom différent. Mais qu'en est-il de l'utilisation d'un conditionnel?

Vous pouvez juste faire:

Public Class Animal 

Public Overridable Function Speak(Optional ByVal speakNormal as Boolean = False) As String 
    Return "Hello" 
End Function 

End Class 

Public Class Dog 
    Inherits Animal 

    Public Overrides Function Speak(Optional ByVal speakNormal as Boolean = False) As String 
     If speakNormal then 
      return MyBase.Speak() 
     Else 
      Return "Ruff" 
     End If 
    End Function 

End Class 

Et puis les appeler comme:

Dim dog As New Dog 
Dim animal As new Animal 
animal.Speak() //"Hello" 
dog.Speak()//"Ruff" 
dog.Speak(true)//"Hello" 

Vous pouvez getTheAnimalInTheDog et faire ilSpeak():

Vous pouvez juste faire:

Public Class Animal 

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

Public MustOverride Function GetTheAnimalInMe() As Animal 

End Class 

Public Class Dog 
    Inherits Animal 

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

    Public Overrides Function GetTheAnimalInMe() As Animal 
     Dim a As New Animal 
     //Load a with the necessary custom parameters (if any) 
     Return a 
    End Function 
End Class 

Et puis encore:

Dim dog As New Dog 
Dim animal As new Animal 
animal.Speak() //"Hello" 
dog.Speak()//"Ruff" 
dog.GetTheAnimalInMe().Speak()//"Hello" 

Hope it helps;)

Questions connexes