3.11 Benutzerdefinierte Operatoren
Die Gründe dafür, selbst Operatoren für Datentypen zu definieren, lassen sich in zwei Gruppen unterteilen:
- Bequemlichkeit: Der Quelltext kann kürzer formuliert werden.
- Implizite Nutzung: Die Operatoren CType, IsTrue und IsFalse werden gegebenenfalls von Code aufgerufen, der vom Compiler automatisch erstellt wird.
Hinweis |
Ein einmal definierter Operator kann nicht mehr geändert werden (Polymorphie für klassengebundene Methoden gibt es nicht in Visual Basic, siehe Abschnitt 3.14, »Polymorphie«). |
3.11.1 Prinzip
Tabelle 3.19 teilt die benutzerdefinierbaren Operatoren in fünf Gruppen ein.
Anwendungsbereich | Operator |
Arithmetik |
+ – * / \ ^ Mod << >> And Or Xor (+- auch unär) |
Vergleich |
= <> > < >= <= Like |
Logik |
Not IsTrue IsFalse And Or Xor |
Zeichenketten |
& |
Typumwandlung |
CType |
Zwei Arten von Operatoren sind nicht neu definierbar, können aber zum Teil auf benutzerdefinierte Operatoren zurückgreifen:
- = selbst kann nicht neu definiert werden, aber alle zusammengesetzten Zuweisungsoperatoren nutzen passende benutzerdefinierte Operatoren für den Nicht-Zuweisungsteil des Operators.
- AndAlso und OrElse selbst können nicht neu definiert werden, aber sie nutzen passende benutzerdefinierte Operatoren von And, Or, IsTrue und IsFalse.
Alle Parameter der benutzerdefinierten Operatoren werden mit ByVal als Wert übergeben. Die Syntax der Definition lautet (optionale Teile stehen in eckigen Klammern und kursive Teile müssen Sie Ihren Bedürfnissen anpassen):
Public Shared [<Modifikatoren>] Operator oper(<Parameter>) As Typ [<Anweisungen>] End Operator |
Hinweis |
Mindestens einer der Operanden (bei Typumwandlungen: oder der Rückgabewert) muss vom Typ der definierenden Klasse sein. |
Tabelle 3.20 zeigt die erlaubten Modifikatoren.
Art | Beschreibung |
Redefinition |
Art des Ersatzes oder Zwangs zu einer Definition (siehe Abschnitt 3.13, »Vererbung« und Abschnitt 3.3.4, »Überladung (Overloads)«) |
Typumwandlung |
Explizit oder implizit (siehe Abschnitt 3.11.4, »Typumwandlung mit CType: Widening und Narrowing«) |
Für jeden benutzerdefinierten Operator fügt der Compiler automatisch eine öffentliche Methode hinzu, deren Name mit op_ beginnt. In Tabelle 3.21 ist dieser Namensteil weggelassen. Die Methodennamen für die Operatoren Not, And, Or und Xor sind gleich für logische und bitweise Operationen. Beim Zusammenspiel mit anderen Programmiersprachen werden bei konkurrierenden logischen und bitweisen Operatoren die logischen ignoriert. Analog wird bei Bitschiebeoperatoren gegebenenfalls nur die vorzeichenbehaftete Version berücksichtigt. Anderen Programmiersprachen wird die ganzzahlige Division \ als normale Division / mit korrekter Bedeutung zur Verfügung gestellt. Statt des Operators kann auch die korrespondierende Methode verwendet werden.
Hinweis |
Die alleinige Definition einer Operatormethode reicht nicht aus, um einen Operator verwenden zu können. |
Methode op_ | Methode op_ | Methode op_ | |||
+ |
Addition |
<< |
LeftShift |
= |
Equality |
+ |
UnaryPlus |
>> |
RightShift |
<> |
Inequality |
- |
Subtraction |
And |
BitwiseAnd |
< |
LessThan |
- |
UnaryNegation |
Or |
BitwiseOr |
> |
GreaterThan |
* |
Multiply |
Xor |
ExclusiveOr |
<= |
LessThanOrEqual |
/ |
Division |
Not |
OnesComplement |
>= |
GreaterThanOrEqual |
^ |
Exponent |
\ |
IntegerDivision |
Like |
Like |
Mod |
Modulus |
& |
Concatenate |
||
Widening CType |
Implicit |
IsTrue |
True |
||
Narrowing CType |
Explicit |
IsFalse |
False |
Hinweis |
Sie müssen selbst darauf achten, dass ein Operator und der Typ seines Rückgabewerts eine sinnvolle Kombination ergeben. Bei IsTrue und IsFalse ist der Typ der Rückgabe zwingend Boolean. |
Schauen wir uns ein Beispiel an. Das folgende Codefragment definiert eine Matrix mit Fließkommazahlen, die mit dem Stringverkettungsoperator & komfortabel ausgegeben werden kann. Die Methode Append() übernimmt die Formatierung. Die Variable ein bestimmt die nötige Einrückung folgender Zeilen, indem sie die bisherige Ausgabe str mithilfe regulärer Ausdrücke durch Leerzeichen ersetzt. PadLeft() sorgt dafür, dass alle Zahlen einer Spalte untereinander stehen. Der Operator & erlaubt durch die zwei Definitionen, dass die Matrix links oder rechts einer Zeichenkette stehen darf.
'...\Klassendesign\Operatoren\Zeichenketten.vb |
Option Strict On Namespace Klassendesign Class Matrix Private val(,) As Double Sub New(ByVal val(,) As Double) Me.val = val End Sub Function Append(ByVal str As String) As String Dim ein As String = _ Text.RegularExpressions.Regex.Replace(str, ".", " ") For row As Int32 = 0 To val.GetUpperBound(0) For col As Int32 = 0 To val.GetUpperBound(1) str += val(row, col).ToString("##0.0").PadLeft(6) Next If row < val.GetUpperBound(0) Then _ str += Environment.NewLine & ein Next Return str End Function Public Shared Operator &(ByVal lhs As Matrix, ByVal rhs As String) _ As String Return lhs.Append(rhs) End Operator Public Shared Operator &(ByVal lhs As String, ByVal rhs As Matrix) _ As String Return rhs.Append(lhs) End Operator End Class ... End Namespace
Eine Matrix auszugeben wird damit sehr einfach:
'...\Klassendesign\Operatoren\Zeichenketten.vb |
Option Strict On Namespace Klassendesign ... Module Zeichenketten Sub Test() Dim M As Matrix = New Matrix(New Double(,) _ {{17.8, –25, 34.1},{9.1, 73.4, 82},{0, –3.4, –5.1}}) Console.WriteLine("Matrix " & M & " und mehr ...") Console.ReadLine() End Sub End Module End Namespace
Die Ausgabe zeigt die Werte zweidimensional und fügt sie nahtlos ein.
Matrix 17.8 –25.0 34.1 9.1 73.4 82.0 0.0 –3.4 –5.1 und mehr ...
3.11.2 Überladung
Bei der Definition eines Operators sollten Sie darauf achten, dass alle für Sie interessanten Parametertypen erfasst werden. Der Fall, der einem als Erstes in den Sinn kommt, hat als Parameter nur Werte vom Typ der definierenden Klasse. Aber auch die Kombination mit Werten eines anderen Typs ist häufig sinnvoll. Beispielhaft zeigt das nächste Codefragment nicht nur die Addition zweier Vektoren, sondern auch die Addition eines Vektors und eines Skalars (Zahl), der links oder rechts vom Vektor stehen darf. Insgesamt werden also drei Definitionen des Operators gebraucht. Um den Quelltext kurz zu halten, sind Überprüfungen auf Nullreferenzen und gleiche Länge der Vektoren weggelassen.
'...\Klassendesign\Operatoren\Ueberladung.vb |
Option Strict On Namespace Klassendesign Class Vek Private val() As Short Sub New(ByVal val() As Short) Me.val = val End Sub Shared Function Add(ByVal v1() As Short, ByVal v2() As Short) As Short() Dim res() As Short = CType(v1.Clone(), Short()) Dim val(v1.Length – 1) As Short For no As Integer = 0 To v1.Length – 1 val(no) = v1(no) + v2(Math.Min(no, v2.Length – 1)) Next Return val End Function Function ToString() As String Dim str As String = "|" For Each d As Double In val : str += d & "|" : Next Return str End Function Public Shared Operator +(ByVal lhs As Vek, ByVal rhs As Vek) As Vek Return New Vek(Add(lhs.val, rhs.val)) End Operator Public Shared Operator +(ByVal lhs As Vek, ByVal rhs As Short) As Vek Return New Vek(Add(lhs.val, New Short() {rhs})) End Operator Public Shared Operator +(ByVal lhs As Short, ByVal rhs As Vek) As Vek Return rhs + lhs End Operator End Class ... End Namespace
Der Plus-Operator lässt sich nun ganz normal verwenden:
'...\Klassendesign\Operatoren\Ueberladung.vb |
Option Strict On Namespace Klassendesign ... Module Überladung Sub Test() Dim V As Vek = New Vek(New Short() {17, –25, 34}) Console.WriteLine("V {0}", V.ToString()) Console.WriteLine("V+V {0}", (V + V).ToString()) Console.WriteLine("V+3 {0}", (V + 3).ToString()) Console.WriteLine("3+V {0}", (3 + V).ToString()) Console.ReadLine() End Sub End Module End Namespace
Die Ausgabe bestätigt die richtige Arbeitsweise des Operators:
V |17|-25|34| V+V |34|-50|68| V+3 |20|-22|37| 3+V |20|-22|37|
Hinweis |
Bei nullbaren Werttypen werden gegebenenfalls auch die korrespondierenden nicht-nullbaren Versionen einer Operatordefinition berücksichtigt. Diese Typen werden in Abschnitt 4.5, »Werttypen mit dem Wert Nothing«, beschrieben. |
3.11.3 Vergleich
Im Gegensatz zu vielen anderen Operatoren müssen korrespondierende Vergleichsoperationen gemeinsam überladen werden.
-
- = und <>
-
- > und <
-
- >= und <=
Im folgenden Beispiel wird die Länge eines Ländernamens stärker gewichtet als die alphabetische Reihenfolge: Kurze Namen erscheinen vor langen. Es wird nur ein Operator explizit kodiert, der entgegengesetzte Operator (das Antonym) ruft die Operatormethode auf und negiert das Ergebnis. Das garantiert, dass sich die gegensätzlichen Operatoren exakt ergänzen.
'...\Klassendesign\Operatoren\Vergleich.vb |
Option Strict On Namespace Klassendesign Class Land Private name As String Sub New(ByVal name As String) Me.name = name End Sub Public Shared Operator <(ByVal l As Land, ByVal r As Land) As Boolean Return l.name.Length <= r.name.Length AndAlso l.name < r.name End Operator Public Shared Operator >(ByVal l As Land, ByVal r As Land) As Boolean Return Not op_LessThan(l, r) ' = Not l < r End Operator Shared Sub Test() Dim L1 As Land = New Land("Finnland") Dim L2 As Land = New Land("Island") Dim L3 As Land = New Land("Schweden") Console.WriteLine("{0}-{1}-{2}", L1.name, L2.name, L3.name) Console.WriteLine("Namen 1<2: {0}", L1.name < L2.name) Console.WriteLine("Namen 1<3: {0}", L1.name < L3.name) Console.WriteLine("Länder 1<2: {0}", L1 < L2) Console.WriteLine("Länder 1<3: {0}", L1 < L3) Console.ReadLine() End Sub End Class End Namespace
3.11.4 Typumwandlung mit CType: Widening und Narrowing
Umwandlungen im weiteren Sinne begegnen uns oft im täglichen Leben. Wenn wir zum Beispiel im Fischladen eigentlich Fisch kaufen wollten, der Laden aber geschlossen ist und wir dennoch nicht unverrichteter Dinge nach Hause gehen wollen, gibt es zwei Möglichkeiten: Entweder begnügen wir uns mit einer Fischdose aus dem Supermarkt, oder wir gehen im Restaurant essen. In Hinblick auf das geplante Essen ist der Umstieg auf ein Restaurant ohne Verlust möglich, während die Dosenvariante die Qualität des Essens mindert. In der Softwaretechnik stehen wir manchmal vor ähnlichen Problemen. Erwartet eine Funktion eine ganze Zahl und soll eine Fließkommazahl als Parameter verwendet werden, können wir diese explizit mittels des Operators CType vor dem Aufruf unter Verlust der Nachkommastellen umwandeln (entspricht der Fischdose). Die andere Richtung, von der ganzen Zahl zur Fließkommazahl, ist verlustfrei möglich und wird auch oft gebraucht. Normalerweise machen wir uns darüber keine Gedanken, da die Umwandlung implizit (automatisch) erfolgt.
Bei der Definition von Konvertierungsoperatoren mit CType ist Folgendes zu beachten:
- Entweder der Start- oder der Zieltyp muss mit der Klasse übereinstimmen, in der der Operator definiert ist.
- Widening CType beschreibt eine implizite Konvertierung, die der Compiler automatisch verwendet.
- Narrowing CType beschreibt eine explizite Konvertierung, die expressis verbis im Quelltext stehen muss.
- Operatoren müssen sich durch mehr als nur Narrowing oder Widening unterscheiden.
- Konvertierungen, die Ausnahmen auslösen oder verlustbehaftet sein können, sollten mit Narrowing als explizit gekennzeichnet werden.
Hinweis |
Der Konvertierungsoperator CType ist die einzige Stelle, wo der Typ des Rückgabewerts Teil der Signatur ist. |
Das nächste Codefragment zeigt als Beispiel eine Autovermietung, bei der zwei Kunden bestellen. Zurzeit sind nur einige Ford Mondeo verfügbar, was sich in der Bestellmethode ausdrückt, die nur diesen Wagentyp entgegennimmt. Der erste Kunde bestellt mit einem Maybach ein teures Auto. Da ein Mondeo weniger Komfort bedeutet, muss durch eine explizite Umwandlung mit CType die Bestellung ermöglicht werden. Demgegenüber bestellt der zweite Kunde eine Ente. Der Vermieter kann dem Kunden ohne Weiteres einen Mondeo geben, da dieser hochwertiger als das bestellte Auto ist. Die Umwandlung erfolgt implizit beim Aufruf der Bestellmethode. Ob Sie die Typkonvertierungen auf zwei Klassen verteilen oder nicht, ist Geschmackssache. Wichtig ist, dass Sie dieselbe Konvertierung nicht durch zwei Klassen doppelt zur Verfügung stellen (die vom Compiler generierte Fehlermeldung ist nicht sehr aussagekräftig).
'...\Klassendesign\Operatoren\Konvertierungen.vb |
Option Strict On Namespace Klassendesign Class Ente : End Class Class Maybach Public Shared Narrowing Operator CType(ByVal auto As Maybach) As Mondeo Console.Write("mit Rückerstattung ") Return New Mondeo() 'um es einfach zu halten End Operator End Class Class Mondeo Public Shared Widening Operator CType(ByVal auto As Ente) As Mondeo Console.Write("auf Kosten des Hauses ") Return New Mondeo() 'um es einfach zu halten End Operator End Class Module Autovermietung Sub Bestellen(ByVal auto As Mondeo) Console.WriteLine("Mondeo erhalten.") End Sub Sub Test() Console.Write("Maybach bestellt und ") Bestellen(CType(New Maybach(), Mondeo)) 'explizit – Narrowing Console.Write("Ente bestellt und ") Bestellen(New Ente()) 'implizit – Widening Console.ReadLine() End Sub End Module End Namespace
Die Ausgabe »mit Rückerstattung« zeigt, dass für den ersten Kunden die Konvertierung mit Narrowing verwendet wurde, während beim zweiten Kunden die Widening-Variante »auf Kosten des Hauses« ausgibt.
Maybach bestellt und mit Rückerstattung Mondeo erhalten. Ente bestellt und auf Kosten des Hauses Mondeo erhalten.
Eine Stolperfalle gibt es bei einer For Each-Schleife. Sie nutzt ausnahmsweise auch explizite Konvertierungen automatisch. Das folgende Codefragment nutzt die einzig vorhandene Konvertierung. Sie ist explizit.
'...\Klassendesign\Operatoren\ForEach.vb |
Option Strict On Namespace Klassendesign Class Zahl Public Shared Narrowing Operator CType(ByVal f As Zahl) As Short Return 0 'um es einfach zu halten End Operator End Class Module ForEach Sub Test() For Each a As Short In New Zahl() {New Zahl()} Console.Write(a & " ") Next Console.ReadLine() End Sub End Module End Namespace
3.11.5 Wahrheitswerte: IsTrue und IsFalse
Ob ein Wert als Wahrheitswert betrachtet wird, hängt davon ab, ob er eines der folgenden Kriterien erfüllt, wobei das erste zutreffende Kriterium genommen wird (Boolean? ist auch erlaubt, siehe Abschnitt 4.5, »Werttypen mit dem Wert Nothing«):
- Der Wert ist schon Boolean.
- Der Wert kann implizit in Boolean konvertiert werden.
- Der Wert definiert die Pseudooperatoren IsTrue und IsFalse.
Möchten Sie die letzte Variante wählen, ist Folgendes zu beachten:
- IsTrue und IsFalse müssen zusammen überladen werden.
- Boolean ist zwingend als Typ der Rückgabe zu verwenden (Boolean? geht nicht).
- Zur Benutzung von AndAlso und OrElse müssen And und Or so definiert sein, dass beide Parameter und das Ergebnis vom Typ der definierenden Klasse sind (natürlich können zusätzlich weitere Signaturen definiert sein).
Das folgende Codefragment zeigt eine Klasse Ort, die die Operatoren IsTrue, IsFalse, Or und And definiert. Jeder der Operatoren macht sich beim Aufruf durch eine Konsolenausgabe bemerkbar, um zu prüfen, ob und in welcher Reihenfolge die Operatoren angesprochen werden. Die Boolean-Operatoren geben außerdem an, welches Objekt (erster Buchstabe) mit welchem Ergebnis (J oder N) gerade getestet wird. Bei den Orten interessieren hier die Temperaturen, sodass »Kuba« als »wahr« und »Island« als »falsch« angesehen werden.
'...\Klassendesign\Operatoren\Wahrheitswerte.vb |
Option Strict On Namespace Klassendesign Class Ort Friend ReadOnly wo As String Sub New(ByVal wo As String) Me.wo = wo End Sub Public Shared Operator IsTrue(ByVal o As Ort) As Boolean Console.Write(o.wo(0) & ":IsTrue :" & If(o.wo = "Kuba", "J ", "N ")) Return o.wo = "Kuba" End Operator Public Shared Operator IsFalse(ByVal o As Ort) As Boolean Console.Write(o.wo(0) & ":IsFalse:" & If(o.wo = "Island", "J ", "N ")) Return o.wo = "Island" End Operator Public Shared Operator Or(ByVal a As Ort, ByVal b As Ort) As Ort Console.Write("Op_| ") Return If(a.wo = "Kuba" Or b.wo = "Kuba", a, b) End Operator Public Shared Operator And(ByVal a As Ort, ByVal b As Ort) As Ort Console.Write("Op_& ") Return If(a.wo <> "Island" And b.wo <> "Island", a, b) End Operator End Class ... End Namespace
Der Test der Operaratoren erfolgt mit einer Liste von Länderpaaren, die in einem Array von Länderarrays abgelegt wird. Die Art der Erzeugung ist hier unwichtig; die Syntax wird in Abschnitt 6.4, »LINQ« erläutert. Der Test innerhalb der Schleife spricht zuerst im ersten Argument der beiden ersten If-Operatoren die Objekte direkt als Wahrheitswerte an. Danach folgt der Test der Logikoperatoren.
'...\Klassendesign\Operatoren\Wahrheitswerte.vb |
Option Strict On Namespace Klassendesign ... Module Wahrheitswerte Sub out(ByVal str As String, ByVal newline As Boolean) Console.Write(str.PadRight(16) & If(newline, Environment.NewLine, "")) End Sub Sub Test() Const h As String = "warm" Const k As String = "kalt" Dim wo() As Ort = New Ort() _ {New Ort("Kuba"), New Ort("Island"), New Ort("Japan")} 'Kombination jeder mit jedem: cross join Dim orte()() As Ort = _ (From o1 In wo From o2 In wo Select New Ort() {o1, o2}).ToArray() For Each o() As Ort In orte out((o(0).wo & " ist " & If(o(0), h, k)).PadRight(21), False) out((o(1).wo & " ist " & If(o(1), h, k)).PadRight(21), True) out("Or ist " & If(o(0) Or o(1), h, k), False) out("OrElse ist " & If(o(0) OrElse o(1), h, k), True) out("And ist " & If(o(0) And o(1), h, k), False) out("AndAlso ist " & If(o(0) AndAlso o(1), h, k), True) Console.WriteLine() Next Console.ReadLine() End Sub End Module End Namespace
Die Ausgabe zeigt das Verhalten der Operatoren:
- Normale Logikoperatoren (And und Or): Der Operator wird aufgerufen, und das Ergebnis, das vom Typ der Klasse (Ort) ist, wird mit IsTrue auf den Wahrheitsgehalt getestet.
- Kurzschlussoperatoren (AndAlso und OrElse): Der erste Operand wird bei AndAlso mit IsFalse und bei OrElse mit IsTrue getestet. Steht das Ergebnis fest, wird (warum auch immer) der Operand erneut getestet; ist das Ergebnis noch unbestimmt, wird der korrespondierende normale Logikoperator aufgerufen.
K:IsTrue :J Kuba ist warm K:IsTrue :J Kuba ist warm Op_| K:IsTrue :J Or ist warm K:IsTrue :J K:IsTrue :J OrElse ist warm Op_& K:IsTrue :J And ist warm K:IsFalse:N Op_& K:IsTrue :J AndAlso ist warm K:IsTrue :J Kuba ist warm I:IsTrue :N Island ist kalt Op_| K:IsTrue :J Or ist warm K:IsTrue :J K:IsTrue :J OrElse ist warm Op_& I:IsTrue :N And ist kalt K:IsFalse:N Op_& I:IsTrue :N AndAlso ist kalt K:IsTrue :J Kuba ist warm J:IsTrue :N Japan ist kalt Op_| K:IsTrue :J Or ist warm K:IsTrue :J K:IsTrue :J OrElse ist warm Op_& K:IsTrue :J And ist warm K:IsFalse:N Op_& K:IsTrue :J AndAlso ist warm I:IsTrue :N Island ist kalt K:IsTrue :J Kuba ist warm Op_| I:IsTrue :N Or ist kalt I:IsTrue :N Op_| I:IsTrue :N OrElse ist kalt Op_& K:IsTrue :J And ist warm I:IsFalse:J I:IsTrue :N AndAlso ist kalt I:IsTrue :N Island ist kalt I:IsTrue :N Island ist kalt Op_| I:IsTrue :N Or ist kalt I:IsTrue :N Op_| I:IsTrue :N OrElse ist kalt Op_& I:IsTrue :N And ist kalt I:IsFalse:J I:IsTrue :N AndAlso ist kalt I:IsTrue :N Island ist kalt J:IsTrue :N Japan ist kalt Op_| J:IsTrue :N Or ist kalt I:IsTrue :N Op_| J:IsTrue :N OrElse ist kalt Op_& J:IsTrue :N And ist kalt I:IsFalse:J I:IsTrue :N AndAlso ist kalt J:IsTrue :N Japan ist kalt K:IsTrue :J Kuba ist warm Op_| J:IsTrue :N Or ist kalt J:IsTrue :N Op_| J:IsTrue :N OrElse ist kalt Op_& J:IsTrue :N And ist kalt J:IsFalse:N Op_& J:IsTrue :N AndAlso ist kalt J:IsTrue :N Japan ist kalt I:IsTrue :N Island ist kalt Op_| I:IsTrue :N Or ist kalt J:IsTrue :N Op_| I:IsTrue :N OrElse ist kalt Op_& I:IsTrue :N And ist kalt J:IsFalse:N Op_& I:IsTrue :N AndAlso ist kalt J:IsTrue :N Japan ist kalt J:IsTrue :N Japan ist kalt Op_| J:IsTrue :N Or ist kalt J:IsTrue :N Op_| J:IsTrue :N OrElse ist kalt Op_& J:IsTrue :N And ist kalt J:IsFalse:N Op_& J:IsTrue :N AndAlso ist kalt
3.11.6 Grafikbibliothek: Addition und Umwandlung von Rechtecken
In diesem Abschnitt erweitern wir die in Abschnitt 3.1.12, »Grafikbibliothek: Beispiel für Kapitel 3 und 4«, eingeführte und zuletzt in Abschnitt 3.10.6, »Grafikbibliothek: Größenänderungen von Rechtecken überwachen«, erweiterte Grafikanwendung. Der neu hinzukommende Additionsoperator erzeugt ein Rechteck, das die beiden Operanden umschließt. Bei der Typkonvertierung von Double nach Rechteck wird die Zahl als Fläche aufgefasst und ein flächengleiches Rechteck erzeugt.
'...\Klassendesign\Graphik\Operatoren.vb |
Option Explicit On Namespace Klassendesign Partial Public Class Rechteck Shared Operator +(ByVal r1 As Rechteck,ByVal r2 As Rechteck) As Rechteck Return New Rechteck(Math.Max(r1.a, r2.a), Math.Max(r1.b, r2.b)) End Operator Shared Widening Operator CType(ByVal fläche As Double) As Rechteck Return New Rechteck(Math.Sqrt(fläche), Math.Sqrt(fläche)) End Operator End Class End Namespace
Zum Test werden zwei Rechtecke erzeugt – das zweite durch die implizite Anwendung der definierten Typumwandlung. Danach werden die beiden Rechtecke mittels des neu definierten Additionsoperators zusammengefasst. Schließlich werden die Größen aller drei Rechtecke ausgegeben.
'...\Klassendesign\Zeichner\Operatoren.vb |
Option Explicit On Namespace Klassendesign Partial Class Zeichner Sub Operatoren() Dim r1 As New Rechteck(9, 2) Dim r2 As Rechteck = 49 Dim r3 As Rechteck = r1 + r2 r1.Größe() : r2.Größe() : r3.Größe() End Sub End Class End Namespace
Zur Kontrolle sehen Sie hier die Ausgabe der Methode Operatoren():
Dimension des Rechtecks: 9x2 Dimension des Rechtecks: 7x7 Dimension des Rechtecks: 9x7
Die nächste Erweiterung erfolgt in Abschnitt 3.13.9, »Grafikbibliothek: neue Vielecke«.
Ihre Meinung
Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de.