Die Community zu .NET und Classic VB.
Menü

Einfache Klassen

 von 

Übersicht 

In diesem Tutorial soll erklärt werden, wie man mit Visual Basic einfache Klassen erstellen und verwenden kann. Dieser Lehrgang soll nur grundlegende Kenntnisse vermitteln.

Mit freundlichen Grüßen
Sebastian Klose

Was sind Klassen?  

Der Oberbegriff für Klasse ist das Objekt. Aber was ist ein Objekt? Visual Basic Programme bestehen fast ausschließlich aus Objekten, so ist beispielsweise jedes Steuerelement (Commandbutton, Textbox, Formular, etc.) ein Objekt. Um dieses theoretische Gebilde des Objekts zu verstehen, verlassen wir kurz Visual Basic und verwenden zum besseren Verständnis ein reales Objekt: Die (Schul-) Klassen.

Wir stellen und vor, es gäbe keinerlei Schulsysteme. Die Eltern aller Kinder unterrichteten diese selber. Das Chaos wäre perfekt, denn keines der Kinder würde gezielt unterrichtet. Jedes Kind hätte einen anderen Wissensstand. Es gäbe keine Zertifikate, die eine bestimmte Bildungsstufe nachweisen, usw. Irgendwann würde jemand versuchen, dieses Chaos zu beseitigen. Er schafft zunächst nur theoretisch ein Gedankengebäude - ein Konzept - in dem Kinder gemäß ihres Alters in Klassen zusammengefasst werden. Diese Klassen haben z.B. die Eigenschaft nur Kinder eines bestimmten Alters aufzunehmen. Gleichzeitig werden die Kinder dieser Klassen durch bestimmte Lehrer und damit durch unterschiedliche Methoden unterrichtet. Natürlich gibt es nicht nur eine Klasse, sondern mehrere, die sich durch verschiedene Eigenschaften und die Anwendung verschiedener Methoden von einander unterscheiden.

Kommen wir nun aber zurück zu Visual Basic: Dort finden wir, wenn wir die Werkzeugsammlung betrachten, eine Reihe von Symbolen, hinter denen sich in dem Moment, in dem wir die Werkzeugsammlung betrachten, nichts weiter als ein theoretisches Gebäude mit Vorschriften verbirgt. Diese Vorschriften definieren, was geschehen soll, wenn eines dieser Konzepte in der Praxis umgesetzt wird. Auch in der objektorientierten Programmierung sprechen wir bei einem solchen theoretischen "Gebäude" (siehe Schule) von einer Klasse.

Es gibt Verfahren - nennen wir es passend zum dem Beispiel mit der Schule "Einschulung" - das aus der Theorie Praxis werden lässt. Unsere theoretische Klasse wird zu einem mehr oder weniger greifbaren Objekt. Bei der Programmierung heißt dieser Vorgang natürlich nicht Einschulung, sondern Instanzierung. Wenn man also das Symbol eines Commandbuttons von der Werkzeugsammlung auf einem Formular platziert, wird die Klasse CommandButton instanziert und man erhält ein CommandButton-Objekt. Dieses Objekt kann, wie die jetzt eingeschulte Klasse, durch bestimmte Eigenschaften klassifiziert werden. Sie bestimmen also beispielsweise die MaximaleStundenProTag-Eigenschaft (Schulklasse) bzw. die Caption-Eigenschaft (CommandButton).

Das Konzept einer Klasse gibt es nur ein einziges Mal. Auch die Rahmenbedingungen, in denen sich eine Klasse bewegen kann, werden nur ein einziges Mal vorgeschrieben. Sämtliche Aufgaben einer Klasse werden nur ein einziges Mal bestimmt. Aber dennoch lässt sich eine Klasse beliebig oft zu einem realen Objekt instanzieren, und mehrere Instanzen einer Klasse (Objekte) können völlig unabhängig von einander agieren.

Beim Programmieren werden die Konzepte und Regeln (die Rahmenbedingungen) einerseits von bestimmten Variablen definiert, andererseits durch Programmcode. Wenn wir eine Klasse instanzieren, schafft Visual Basic ein Objekt vom Typ dieser Klasse. Das Objekt enthält den Code der zuvor durch die Klasse definiert wurde. Der Code wiederum bestimmt, was geschieht, wenn man eine bestimmte Methode auf das Objekt anwendet oder eine Eigenschaft des Objekts verändert.

In VB-Code könnte ein derartiges Objektmodell einer Schule in etwa so dargestellt werden:

Option Explicit
        
Dim Schule1 As New Schule
Dim Klasse1a As New Klasse
Dim Klasse1b As New Klasse
Dim Klasse2a As New Klasse
Dim Klasse2b As New Klasse

Private Sub Schule1_Einschulung()

    Klasse1a.Raumnummer = 1
    Klasse1b.Raumnummer = 2
    Klasse2a.Raumnummer = 3
    Klasse2b.Raumnummer = 4

    Klasse1a.StarteUnterricht "Mathe"
    Klasse1b.StarteUnterricht "Deutsch"
    Klasse2a.StarteUnterricht "Sport"
    Klasse2b.StarteUnterricht "Englisch"

End Sub

Private Sub Schule1_EsSchellt(ByVal Pausennummer As Integer)

    Klasse1a.InPause
    Klasse1b.InPause
    .
    .

End Sub

Listing 1: Achtung: dieser Code kann nicht ausgeführt werden!

Die erste Klasse  

Nun wollen wir die erste Klasse in Visual Basic realisieren. Dazu erstellen wir zunächst ein neues Projekt vom Typ "Standard EXE" und fügen diesem mit einem Klick auf den Menüpunkt Klassenmodul hinzufügen im Menü Projekt eine neue Klasse hinzu.


Abbildung 1: Screenshot

Im nun erscheinenden Dialogfeld wählen wir "Klassenmodul" aus und geben unsere Klasse im Eigenschaftsfenster noch einen Namen, z.B. "TestKlasse". Als nächstes müssen wir die oben genannten "Rahmenbedingungen" für die Klasse schaffen. Dazu fügen wir der Klasse eine Eigenschaft hinzu (der Name der Eigenschaft soll einfach "Eigenschaft" sein). Im Klassenmodul sollte nun folgender Code enthalten sein:

Option Explicit

Private m_strEigenschaft As String

Public Property Get Eigenschaft() As String
  Eigenschaft = m_strEigenschaft
End Property

Public Property Let Eigenschaft(ByVal NewValue As String)
  m_strEigenschaft = NewValue
End Property

Listing 2: Quelltext einer Eigenschaft

Nun möchten wir aber, dass unsere Eigenschaft einen Standardwert bekommen kann, also fügen wir noch eine Funktion (welche in Klassen übrigens Methoden genannt werden) hinzu:

Public Function SetzeStandard()
   Eigenschaft = "Standardwert"
End Function

Listing 3: Quelltext einer Methode

Jetzt müssen wir noch den Code für das Formular schreiben. Zunächst platzieren wir auf dem Formular aber 3 CommandButtons und eine TextBox. Das ganze sollte dann in etwa so aussehen:


Abbildung 2: Screenshot

Der Quellcode sollte nun folgender sein (natürlich ohne die Zeilennummern!):

1 : Option Explicit
2 : 
3 : Dim Objekt As New TestKlasse
4 :
5 :
6 : Private Sub Command1_Click()
7 :
8 :   Objekt.Eigenschaft = Text1.Text
9 :
10: End Sub
11:
12: Private Sub Command2_Click()
13:
14:   Objekt.SetzeStandard
15:
16: End Sub
17:
18: Private Sub Command3_Click()
19:
20:   MsgBox Objekt.Eigenschaft
21:
22: End Sub

Listing 4

Zunächst wird hier in Zeile 3 ein Objekt aus der grade definierten Klasse erstellt. Das Schüsselwort New sorgt dafür, dass unser Objekt auch wirklich instanziert wird, und somit verwendet werden kann. In Zeile 8 sind schon die Parallelen zu den Objekten aus der Werkzeugsammlung (Commandbuttons etc.) ersichtlich. Alle Methoden und Eigenschaften einer Klasse werden (genau wie bei den Controls aus der Werkzeugsammlung) durch den Namen des Objektes + Punkt + Name der Eigenschaft/Methode angesprochen.

Was nun noch etwas störend ist an diesem Beispiel, ist dass unsere Eigenschaft nicht zu Beginn ihren Standardwert hat und dieser erst durch einen Aufruf der Methode SetzeStandard() hergestellt wird. Um dieses Problem zu lösen besitzen alle Objekte 2 vordefinierte Methoden, nämlich den Konstruktor und den Destruktor. Der Konstruktor wird ausgeführt sobald eine Instanz der Klasse geschaffen wurde (also in Zeile 3). Der Destruktor wird beim Beenden des Programms ausgeführt, in ihm könnte beispielsweise belegter Arbeitsspeicher der Klasse wieder freigegeben werden. Wir benötigen allerdings zunächst nur den Konstruktor. Wir können ihn der Klasse ganz einfach hinzufügen, indem wir ihr die Methode Class_Initialize() implementieren:

Private Sub Class_Initialize()
  SetzeStandard ' Standardwert der Eigenschaft setzen
End Sub

Listing 5: Konstruktor Beispiel

Und siehe da, wenn wir die Anwendung nun starten und auf "Anzeigen" klicken, wird tatsächlich der Standardwert ausgegeben.

Als letztes wollen wir der Klasse noch ein Ereignis hinzufügen. Jedes Mal, wenn die Eigenschaft den Standardwert bekommt, soll das Ereignis "StandardGesetzt" ausgelöst werden. Dazu ändern wir zunächst den Code der Klasse wie folgt ab:

1 : Option Explicit
2 :
3 : Public Event StandardGesetzt()
4 :
5 : Private m_strEigenschaft As String
6 : Private Const STANDARD_STRING = "Standardwert"
7 :
8 :
9 : Public Property Get Eigenschaft() As String
10:   Eigenschaft = m_strEigenschaft
11: End Property
12:
13: Public Property Let Eigenschaft(ByVal NewValue As String)
14: 
15:   m_strEigenschaft = NewValue
16: 
17:   If Eigenschaft = STANDARD_STRING Then 
18:     RaiseEvent StandardGesetzt
19:   End If 
20: End Property
21:
22: Public Function SetzeStandard()
23:   Eigenschaft = STANDARD_STRING
24: End Function
25:
26: Private Sub Class_Initialize()
27:   SetzeStandard
28: End Sub

Listing 6: Ereignis Beispiel

Zu den Änderungen:

  • In Zeile 3 teilen wir Visual Basic mit, dass diese Klasse ein Event (=Ereignis) auslösen soll, diesen wird mit der RaiseEvent - Funktion in Zeile 18 getan
  • Der Standardwert unserer Eigenschaft wurde in einer Konstanten abgelegt

Jetzt muss der Code des Formulars nur noch ein wenig abgewandelt werden, damit uns das Ereignis der Klasse dort zur Verfügung steht:

1 : Option Explicit
2 :
3 : Dim WithEvents Objekt As TestKlasse
4 :
5 :
6 : Private Sub Form_Load()
7 :
8 :   Set Objekt = New TestKlasse
9 :
10: End Sub
11:
12: Private Sub Command1_Click()
13:
14:   Objekt.Eigenschaft = Text1.Text
15:
16: End Sub
17:
18: Private Sub Command2_Click()
19:
20:   Objekt.SetzeStandard
21:
22: End Sub
23:
24: Private Sub Command3_Click()
25:
26:   MsgBox Objekt.Eigenschaft
27:
28: End Sub
29:
30: Private Sub Objekt_StandardGesetzt()
31:
32:   MsgBox "Es wurde der Standardwert gesetzt"
33:
34: End Sub

Listing 7

Zu den Änderungen:

  • Das Schlüsselwort, um an die Ereignisse eines Objektes heranzukommen, lautet in VB WithEvents (siehe Zeile 3)
  • Das Erstellen des eigentlichen Objektes wurde in die Form_Load() - Funktion verlagert, da VB ein gleichzeitiges WithEvents und New nicht unterstützt
  • In Zeile 30 wird dann das Event definiert, wie man es auch von CommandButtons, TextBoxes, etc kennt.

Polymorphismus in Visual Basic  

Mit Polymorphismus meint man die Eigenschaft, Objekte aus anderen Objekten zu erstellen, auch Vererbung genannt. Dies wird von Visual Basic leider erst ab .NET richtig unterstützt. Die einzige Möglichkeit der Vererbung in VB 6 sind die sogenannten Interfaces. Dieses sind abstrakte Klassen, d. h. Klassen, die nur die Funktionsrümpfe enthalten. Diese Interfaces können dann von beliebigen Klassen implementiert werden. Dadurch "erbt" die Klasse alle Funktionen des Interfaces. Dies hat den Vorteil, dass sich alle Klassentypen die ein bestimmtes Interface implementiert haben, untereinander zuweisen lassen. Hier ein Beispiel dazu:

Als ersten wollen wir unser Interface definieren, dazu fügen wir einem neuen Projekt eine Klasse hinzu, die wir "ITier" nennen (das "I" steht dabei für Interface). Sie soll folgenden Code enthalten:

Option Explicit

Public Function Essen()
End Function

Public Function Schlafen()
End Function

Listing 8: Eine abstrakte Klasse

Da man aus solchen abstrakten Klassen keine Objekte erstellen kann, brauchen wir noch weitere Klassen, die dieses Interface implementieren. Deswegen fügen wir als nächstes die Klasse "Hund" hinzu. Sie enthält folgenden Code:

Option Explicit

Implements ITier


Private Function ITier_Essen() As Variant
  MsgBox "Der Hund isst"
End Function

Private Function ITier_Schlafen() As Variant
  MsgBox "Der Hund schläft"
End Function

Public Function Beiss()
  MsgBox "Der Hund beisst"
End Function

Listing 9

Erklärung:

  • In der zweiten Zeile wird durch das Schlüsselwort Implements unser Interface eingebunden. Alle im Interface definierten Funktionsrümpfe müssen von der Hund-Klasse mit Code gefüllt, oder zumindest als leere Funktionen implementiert werden.
  • Durch die neue Methode Beiss() wird der Hund spezialisiert. Er ist zwar immer noch ein Tier (weil er dieses Interface implementiert), aber er hat im Vergleich zu einem normalen Tier weitere Eigenschaften.

Da es wenig Sinn hat Interfaces zu nutzen, wenn es nur eine Klasse gibt, die dieses implementiert, definieren wir noch eine zweite, und zwar die Klasse "Katze":

Option Explicit

Implements ITier


Private Function ITier_Essen() As Variant
  MsgBox "Die Katze isst"
End Function

Private Function ITier_Schlafen() As Variant
  MsgBox "Die Katze schläft"
End Function

Public Function Kratz()
  MsgBox "Die Katze kratzt"
End Function

Listing 10

Die Katze unterscheidet sich vom Hund in sofern, dass sie nicht beißen kann, dafür kann sie aber kratzen. Trotzdem bleibt sie, genau wie der Hund, aber ein Tier, weil sie ebenfalls das Interface implementiert.

Jetzt müssen wir nur noch den Code unseres Formulars aufsetzten. Zunächst bekommt unser Formular 4 CommandButtons (Captions: Essen; Schlafen; Beißen; Kratzen). Dazu kommen noch zwei OptionButtons mit den Aufschriften Hund + Katze. Das ganze sieht dann in etwa so aus:


Abbildung 3: Screeshot

Der Code sollte so aussehen:

Option Explicit

Dim Tier As ITier

Private Sub Form_Load()
  Set Tier = New Hund
End Sub

Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
  Set Tier = Nothing
End Sub

Private Sub Command1_Click()
  Tier.Essen
End Sub

Private Sub Command2_Click()
  Tier.Schlafen
End Sub

Private Sub Command3_Click()
  Dim objTempHund As Hund
    If Not TypeOf Tier Is Hund Then
      MsgBox "Das Tier ist kein Hund und kann nicht beißen"
    Else
      Set objTempHund = Tier
      objTempHund.Beiss
    End If
End Sub

Private Sub Command4_Click()
  Dim objTempKatze As Katze
    If Not TypeOf Tier Is Katze Then
      MsgBox "Das Tier ist keine Katze und kann nicht kratzen"
    Else
      Set objTempKatze = Tier
      objTempKatze.Kratz
    End If
End Sub

Private Sub Option1_Click()
  Set Tier = New Hund
End Sub

Private Sub Option2_Click()
  Set Tier = New Katze
End Sub

Listing 11

Erklärungen:

Zunächst definieren wir die Variable Tier vom Typ ITier. Da dies ein Interface ist und aus diesem kein Objekt erstellt werden kann, fällt das Wort New hier weg. Stattdessen wird im Form_Load() - Ereignis ein neuer Hund instanziert. Dies ist nur dadurch möglich, dass der Hund das Interface ITier implementiert hat.

Mit den beiden OptionButtons kann man zwischen einem Hund und einer Katze wählen. Mit einem Klick auf "Essen" oder "Schlafen" wird die entsprechende Funktion aus dem Interface aufgerufen, da diese dort nur deklariert, jedoch nicht definiert ist, wird es an die Klasse, die das Interface implementiert hat weitergeleitet. Also entweder an den Hund oder die Katze, je nachdem als was das Tier momentan definiert ist.

Bei einem Klick auf "Beißen" wird zunächst kontrolliert, ob das Tier ein Hund oder eine Katze ist. Dies geschieht mit der VB-Funktion TypeOf. Wenn es wirklich ein Hund ist, wird unser Tier in eine spezialisierte Klasse vom Typ Hund übertragen, es bleibt jedoch die selbe Klasse, es wird dabei keine neue Klasseninstanz erstellt. Das ist nötig, da das Objekt Tier vom Typ ITier ist und die Methode Beiss() nicht kennt. Der Hund kennt diese aber, da sie in ihm definiert wurde. Der selbe Vorgang wird dann auch mit der Katze wiederholt.

Zusammenfassung  

Dies war ein einfacher Einstieg in die Welt der Klassen(module). Für Fragen steht Ihnen der Autor gerne zur Verfügung. Im Anhang finden Sie zwei Beispiele und dieses Tutorial als Worddokument.

Tutorial und Beispielprojekte als Download [102000 Bytes]

Ihre Meinung  

Falls Sie Fragen zu diesem Tutorial haben oder Ihre Erfahrung mit anderen Nutzern austauschen möchten, dann teilen Sie uns diese bitte in einem der unten vorhandenen Themen oder über einen neuen Beitrag mit. Hierzu können sie einfach einen Beitrag in einem zum Thema passenden Forum anlegen, welcher automatisch mit dieser Seite verknüpft wird.