Visual Basic .NET: Überladung von Funktionen
Erneut wollen wir das Beispiel des vorigen Kapitels um einen weiteren Aspekt erweitern. Jetzt wird die Funktion überladen.
Public Class Form1 Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load MessageBox.Show(Verdoppeln(2)) MessageBox.Show(Verdoppeln(2.4)) End Sub Private Function Verdoppeln(ByVal Zahl As Integer) As Integer Return 2 * Zahl End Function End Class
4 4
Wahrscheinlich erwarten Sie jetzt die Ausgaben 4 und 4,8, doch in Wahrheit wird zweimal 4 ausgegeben. Der Parameter der Funktion Verdoppeln muss vom Typ Integer sein, 2.4 ist jedoch ein Double-Literal. Damit kein Fehler erzeugt wird, wird der Double-Wert in einen Integer-Wert umgewandelt, also eine Ganzzahl. Aus 2.4 wird 2. Dieser Wert wird an die Funktion übergeben, welche diesen korrekt verdoppelt (mit dem Ergebnis 4). Trotzdem ist das Ergebnis falsch, denn wir beabsichtigten nicht, 2 zu verdoppeln, sondern 2,4.
Die offensichtliche Lösung für dieses Problem ist, in der Funktionsdeklaration „Integer“ durch „Double“ zu ersetzen. Das löst das Problem: Beide Funktionsaufrufe im folgenden Beispiel arbeiten korrekt.
Public Class Form1 Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load MessageBox.Show(Verdoppeln(2)) MessageBox.Show(Verdoppeln(2.4)) End Sub Private Function Verdoppeln(ByVal Zahl As Double) As Double Return 2.0 * Zahl End Function End Class
4,0 4,8
In der Funktion Verdoppeln habe ich die 2 (Typ Integer) durch eine 2.0 (Typ Double) ersetzt, da Operationen mit zwei gleichen Datentypen generell schneller sind. Die Lösung mit Double-Parameter und -Rückgabetyp ist allerdings nicht die feine Art, da sie die Sache unnötig verkompliziert. Wenn man nämlich wie beim ersten Funktionsaufruf einen Integer-Literal übergibt, muss dieser erst aufwändig in Double umgewandelt werden. Will man das Ergebnis dann noch auf einer Integer-Variable speichern oder an einen Integer-Parameter übergeben, wird Double nochmals zurück konvertiert.
Zusammengefasst: Integer-Parameter und -Rückgabetyp bedeuten weniger Rechenzeit, dafür oft falsche Ergebnisse. Double-Parameter und -Rückgabetyp bedeuten immer richtige Ergebnisse, aber unnötigen Rechenaufwand. Wie kann man nun das Beste beider Varianten miteinander verbinden? So:
Public Class Form1 Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load MessageBox.Show(Verdoppeln(2)) MessageBox.Show(Verdoppeln(2.4)) End Sub Private Function Verdoppeln(ByVal Zahl As Integer) As Integer Return 2 * Zahl End Function Private Function Verdoppeln(ByVal Zahl As Double) As Double Return 2.0 * Zahl End Function End Class
4 4,8
Wenn Sie jetzt doppelt sehen, sehen Sie absolut richtig. Jetzt haben wir nämlich zwei Funktionsdeklarationen und -definitionen. Es handelt sich aber um dieselbe Funktion. Jetzt haben wir die Funktion überladen. Das bedeutet, dass mehrere Varianten von Parametern zur Verfügung stehen. Diese Varianten heißen ebenfalls Überladungen. In der ersten Überladung wird hier ein Integer-Parameter übergeben und ein Integer-Wert zurückgegeben, die zweite Überladung benutzt Double-Werte. Der Visual-Basic-Compiler erkennt beim Erstellen des Programmes automatisch, welche der Überladungen für welchen Funktionsaufruf benutzt werden soll. Manchmal weiß aber auch der Compiler nicht, welche Überladung die richtige ist. Falls Sie ein Beispiel wollen, ersetzen Sie in der zweiten Überladungen „Double“ durch „Single“. Der zweite Funktionsaufruf stellt den Computer dann vor ein Dilemma: Soll er von Double zu Single oder von Double zu Integer umwandeln (vor allem weil in beiden Fällen der Wertebereich reduziert wird)?
Alternative: Optionale Parameter
BearbeitenAuch in den von .NET mitgelieferten Funktionen wird Überladung gerne und häufig eingesetzt. Ein Beispiel ist die MessageBox.Show-Funktion, die über nicht weniger als 21 Überladungen verfügt. Sie kennen bis jetzt die folgenden beiden Überladungen:
Show(text As String) As DialogResult Show(text As String, caption As String) As DialogResult
Hier sieht man eine weitere nützliche Eigenschaft von Überladungen: Sie können unterschiedlich viele Parameter haben. Eine Überladung kann auch ohne Parameter auskommen. (Natürlich darf es pro Funktion nur höchstens eine Überladung ohne Parameter geben, wegen der Eindeutigkeit.)
Oft werden Überladungen deshalb für zusätzliche optionale Parameter verwendet. Oben ist der Parameter caption optional. Das heißt, man kann die Funktion unter Angabe dieses Parameters aufrufen, kann den Parameter aber weglassen. Dann wird meist ein Standardwert verwendet (in diesem Fall wird für caption, den Titel des Hinweisfensters, der Name des aufrufenden Programms benützt). In schlechten Programmen (und davon gibt es leider ziemlich viele) wird in der Überladung ohne den optionalen Parameter nur die andere Überladung aufgerufen, wobei für den optionalen Parameter der Standardwert eingesetzt wird. Zum Beispiel würde eine Implementation eines Hinweisfeldes dann so aussehen (hier ist der Standardwert für den optionalen Parameter ""
, also eine leere Zeichenkette):
Private Sub Hinweisfeld(ByVal Text As String) Hinweisfeld(Text, "") End Sub Private Sub Hinweisfeld(ByVal Text As String, ByVal Titel As String) MessageBox.Show(Text, Titel) End Sub
Solche optionalen Parameter kann man aber auch einfacher haben. Mit Optional-Parametern (Optional ist ein Schlüsselwort) gab es in Visual Basic nämlich lange vor Überladungen eine einfache Implementationsmöglichkeit, die man sich auch hier zu Nutze machen kann:
Private Sub Hinweisfeld(ByVal Text As String, Optional ByVal Titel As String = "") MessageBox.Show(Text, Titel) End Sub
Hier ist der Parameter Titel als Optional deklariert. Wenn für ihn kein Wert übergeben wird, wird der Standardwert verwendet. Der Standardwert (hier ""
) wird dem Parameter, wie oben zu sehen, quasi zugewiesen. Das hat jedoch nichts mit der Zuweisungsoperation zu tun, sondern ist Teil der Visual-Basic-Sprachsyntax.
Eine Funktion kann beliebig viele Optional-Parameter haben, jedoch darf nach einem solchen optionalen Parameter kein weiterer nicht-optionaler Parameter folgen. Kurz: Alle optionalen Parameter müssen hinter allen nicht-optionalen stehen. Theoretisch kann man auch Überladungen und optionale Parameter mischen, dies sollten Sie aber tunlichst vermeiden, da sich beide Konzepte gegenseitig verkomplizieren.