Sinnvolles Nutzen von Klassen und Vererbung

    • VB.NET

    Es gibt 2 Antworten in diesem Thema. Der letzte Beitrag () ist von Niko Ortner.

      Sinnvolles Nutzen von Klassen und Vererbung

      In diesem Tutorial möchte ich anhand einer Aufgabenstellung erklären, wie man Klassen und Klassenvererbung sinnvoll einsetzen kann.

      Als Beispiel:

      Das Ziel ist es eine Konsolenanwendung zu erstellen, die diverse benutzerdefinierte Befehle ausführen kann.
      Die Syntax bei diesem Beispil ist:
      /(Befehl)[~(Parameter)]
      Also könnte ein Befehl zum Beispiel so aussehen: "/Start~C:\Users\Administrator\Desktop\Testanwendung1.exe"

      Es ist nun nicht sinnvoll die gesammte Auswahl der Befehle in eine Select Case - Verzweigung zu packen. Schonmal wegen der Übersichtlichkeit und der eingeschränkten Möglichkeit weitere Befehle hinzuzufügen.

      VB.NET-Quellcode

      1. Dim LastLine As String = Console.ReadLine
      2. Select Case LastLine
      3. Case "/Start"
      4. If LastLine.Contains("~") Then
      5. Process.Start(LastLine.Split("~"c).Last)
      6. End If
      7. 'und so weiter...
      8. End Select


      Die Auslagerung in eine Klasse kommt hier sehr praktisch.

      Dazu möchte ich zuerst erklären, was das Schlüsselwort "Inherits" bedeutet.
      Das bekannteste Beispiel ist der Typ Object. Alle .Net Typen sind Object untergeordnet, was wiederum heißt, dass sie von Object erben.
      Um es an einem Beispiel zu zeigen:

      VB.NET-Quellcode

      1. For Each i As Object In {"Test", "Anderer Test", "Sonstwas"}
      2. Next

      Natürlich ist das Array vom Typ String() und damit "As Object" sehr unsauber.

      Um noch einen Schritt weiter zu gehen: Das hier verwendete Array enthält unterschiedliche Typen. Hier wäre ein "As String" nicht mehr möglich, weil das mit den Typen Integer und StreamReader nicht mehr zusammenpasst. Auch "As Integer" ist nicht möglich, weil das mit den jeweils anderen Typen nicht übereinstimmt.

      VB.NET-Quellcode

      1. For Each i As Object In {"Test", 31415, New IO.StreamReader("Pfad")}
      2. Next

      Natürlich wird jeder Option Strict On Programmierer sofort sagen, dass das ein völliger Blödsinn ist.

      Aber wenn es darum geht eine Auflistung von mehreren verschiedenen Objekten zu erstellen um etwas abzufragen, was alle gemeinsam haben wird Klassenvererbung interessant.

      Um ein Grundgerüst zu erhalten erstellen wir eine neue Konsolenanwendung und fügen eine endlos-Schleife ein:

      VB.NET-Quellcode

      1. Sub Main()
      2. Do
      3. Loop
      4. End Sub


      Damit das Hauptprogramm schön übersichtlich bleibt fügen wir dem Projekt eine neue Klasse hinzu und nennen diese z.B. "Commands".
      In dieser Klasse werden alle Befehle untergebracht, über die das Programm verfügen soll.

      Um die Klassenvererbung erst möglich zu machen fügen wir dieser Klasse die Basisklasse aller Befehle hinzu. Dabei darf das Schlüsselwort "MustInherit" nicht vergessen werden, weil es angibt, dass die Klasse nicht "alleine" verwendet werden kann. Also wird "Dim Test As CommandBaseClass" nicht funktionieren (kann es ja auch nicht, denn die Basisklasse alleine ist nutzlos).
      Diese Klasse nennen wir "CommandBaseClass"

      VB.NET-Quellcode

      1. Public MustInherit Class CommandBaseClass
      2. End Class


      Das alleine reicht noch nicht. Jetzt müssen wir überlegen, welche gemeinsamen Eigenschaften, Prozeduren, etc. alle Befehle haben sollen.
      In diesem Beispiel erhalten alle Befehle eine Variable "InitializeString As String", die angibt, wie der Befehl aussehen soll (z.B. "/Start"), eine Variable "Description As String", die Informationen über den Befehl angibt (z.B. "Startet eine Anwendung oder öffnet eine Datei mit dem angegebenen Pfad").
      Die einzige Prozedur, über die Befehle verfügen ist die "Start" Prozedur, in der der Code des Befehls abgearbeitet wird. Ihr wird auch der angegebene Parameter übergeben.

      VB.NET-Quellcode

      1. Public MustInherit Class CommandBaseClass
      2. Public InitializeString As String
      3. Public Description As String
      4. Public MustOverride Sub Start(ByVal Parameter As String)
      5. End Class


      Damit ist die Basisklasse fertig.

      Jetzt können alle Befehle als Klassen hinzugefügt werden.
      Um es am Befehl "Start" zu zeigen:

      VB.NET-Quellcode

      1. Public Class Command_Start
      2. Inherits CommandBaseClass 'Damit wird angegeben, dass Command_Start von CommandBaseClass erbt
      3. End Class


      Normalerweise wird automatisch die Sub "Public Overrides Sub Start(ByVal Parameter As String)" hinzugefügt. Falls dies nicht der Fall ist muss das nachgeholt werden.

      VB.NET-Quellcode

      1. Public Class Command_Start
      2. Inherits CommandBaseClass
      3. Public Overrides Sub Start(ByVal Parameter As String)
      4. End Sub
      5. End Class


      Um den Befehl "Start" nun verwendbar zu machen müssen den beiden vorher deklarierten Variablen "InitializeString" und "Description" in der Sub "New" die entsprechenden Werte hinzugefügt werden.
      Und um Platz zu sparen alles auf einmal: In der Sub "Start" wird der Code eingefügt, der für diesen Befehl verwendet werden soll. In diesem Fall fünf Zeilen.
      Die fertige Klasse für den Start Befehl:

      VB.NET-Quellcode

      1. Public Class Command_Start
      2. Inherits CommandBaseClass
      3. Public Sub New()
      4. InitializeString = "/Start"
      5. Description = "Startet eine Anwendung oder öffnet eine Datei mit dem übergebenen Pfad"
      6. End Sub
      7. Public Overrides Sub Start(ByVal Parameter As String)
      8. If Parameter = "" Then
      9. Console.WriteLine("Es wurde kein Parameter angegeben")
      10. Else
      11. Process.Start(Parameter)
      12. End If
      13. End Sub
      14. End Class



      Als nächstes wird der Klasse "Commands" eine Funktion hinzugefügt, die es erleichtert alle Befehle aufzulisten.

      VB.NET-Quellcode

      1. Shared Function GetAllCommands() As List(Of CommandBaseClass)
      2. Return New List(Of CommandBaseClass) From {New Command_Start} 'In das Array werden alle Befehle mit dem Schlüsselwort New eingetragen. Das ist der einzige Makel, der mich zur Zeit stark stört.
      3. End Function



      Damit wäre die Klasse "Commands" abgeschlossen (natürlich können weitere Befehle hinzugefügt werden).

      Das eigentliche Programm ist jetzt ein Kinderspiel.
      Es muss nur ein paar Dinge machen:
      Auflistung aller Befehle, Eingabe des Benutzers aufnehmen, anhand des Anfangs herausfinden, welcher Befehl ausgeführt werden soll, die Sub "Start" des Befehls starten und falls vorhanden den Parameter übergeben.
      Mein Beispiel sieht so aus:

      VB.NET-Quellcode

      1. Sub Main()
      2. 'Ausgabe aller Befehle
      3. Console.WriteLine("Die verfügbaren Befehle sind:")
      4. For Each i As Commands.CommandBaseClass In Commands.GetAllCommands
      5. Console.WriteLine(i.InitializeString)
      6. Next
      7. Do
      8. 'Aufnahme der Eingabe
      9. Console.WriteLine("Bitte geben Sie einen Befehl ein")
      10. Dim LastLine As String = Console.ReadLine
      11. Dim Done As Boolean = False
      12. 'Den entsprechenden Befehl starten
      13. For Each i As Commands.CommandBaseClass In Commands.GetAllCommands
      14. If i.InitializeString = LastLine.Split("~"c).First Then
      15. 'Wenn ein Parameter eingegeben wurde wird dieser der Sub Start übergeben, falls nicht wird "" übergeben
      16. i.Start(If(LastLine.Contains("~"), LastLine.Substring(LastLine.IndexOf("~"c)), ""))
      17. Done = True
      18. End If
      19. Next
      20. 'Wenn ein passender Befehl gefunden wurde wird "Vorgang abgeschlossen" ausgegeben, falls nicht bedeutet das, dass der Benutzer eine ungültige Eingabe gemacht hat.
      21. If Done Then
      22. Console.WriteLine("Vorgang abgeschlossen")
      23. Else
      24. Console.WriteLine("Ungülgige Eingabe")
      25. End If
      26. Loop
      27. End Sub


      Dieses Beispiel kann sicherlich noch optimiert werden, aber es geht im Wesentlichen darum zu zeigen, wofür die Klassenvererbung verwendet werden kann.


      Damit wäre dieses Tutorial fertig.

      Auf Verbesserungsvorschläge, etc. würde ich mich freuen.

      Im Anhang befindet sich noch das Projekt, in dem ein paar Befehle hinzugefügt wurden.
      Dateien
      "Luckily luh... luckily it wasn't poi-"
      -- Brady in Wonderland, 23. Februar 2015, 1:56
      Desktop Pinner | ApplicationSettings | OnUtils
      Ich bekomme einen Error und zwar den hier:



      Fehler 1 "end of"-Anweisung erwartet. C:\Users\******\AppData\Local\Temporary Projects\ConsoleApplication1\Commands.vb 4 46 ConsoleApplication1


      Das liegt vielleicht daran, das ich es mit VB08 gemacht habe. Geht diese Variante auch über VB08 ?



      MFG
      Ooooh, mein Gott. Ich habe hier schon seit mindestens 141 Tagen nicht mehr rein geschaut. Sorry.

      Es sieht so aus, als wäre das gemeint:

      VB.NET-Quellcode

      1. Return New List(Of CommandBaseClass) From {New Command_Help, New Command_WriteLine, New Command_Close, New Command_ReadLine, New Command_PrintMemory, New Command_Clear, New Command_Start}


      Möglicherweise gibt es das From Schlüsselwort in VB2008 noch nicht.

      Schreib es um auf:

      VB.NET-Quellcode

      1. Dim NewList As New List(Of CommandBaseClass)
      2. NewList.Add(New Command_Help)
      3. NewList.Add(New Command_WriteLine)
      4. NewList.Add(New Command_Close)
      5. NewList.Add(New Command_ReadLine)
      6. NewList.Add(New Command_PrintMemory)
      7. NewList.Add(New Command_Clear)
      8. NewList.Add(New Command_Start)
      9. Return NewList

      So sollte es auch in VB2008 funktionieren.


      PS: Ich hoffe es ist kein allzugroßes Problem, dass das Topic schon veraltet ist.
      "Luckily luh... luckily it wasn't poi-"
      -- Brady in Wonderland, 23. Februar 2015, 1:56
      Desktop Pinner | ApplicationSettings | OnUtils