Ein konkretes Klassen-Projekt zum Lernen und Entwickeln

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 11 Antworten in diesem Thema. Der letzte Beitrag () ist von VaporiZed.

    Ein konkretes Klassen-Projekt zum Lernen und Entwickeln

    Hallo liebes Forum,

    nun ist es soweit. Ich habe mich rangesetzt und mir ein richtiges Beispiel (geeignetes Problem) ausgedacht, das ich verfolgen will, um ein wenig mehr mit Klassen zu machen.
    Im alten Thread hatte ich keine guten Beispiele und ich kannte mich nicht so gut aus. Hier darf jeder gerne seine Ideen einbringen. :)


    Ich habe mich an @VaporiZeds Beispiel Lebewesen gehalten und habe das Ganze anhand der biologischen Systematik strukturiert. "Lebewesen" ist im Programmtechnischen zu allgemein und damit MustInherit. Ebenso Säugetiere (diese haben aber schon bestimmte Eigenschaften), dann kommen die Paarhufer mit deren Eigenschaften, dann die Echten Schweine und zu guter letzt das Hausschwein. (Die Struktur ist etwas abgekürzt, aber das Prinzip ist klar ;) )

    1.) Ich möchte als Erstes ein Hausschwein erstellen. Wie übergebe ich am geschicktesten die Parameter?
    2.) Braucht es i.A. eine Public Shared Function CreateInstance?

    Ich stelle schon mal den ersten Code rein. Ist noch nackig.

    Viele Grüße

    Bartosz

    VB.NET-Quellcode

    1. 'Option Strict On wurde in den Projekteigenschaften gesetzt.
    2. 'Assembly-Sprache ist Deutsch (Deutschland).
    3. Public Class Form1
    4. Private HS As New Hausschwein
    5. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    6. Debug.WriteLine("")
    7. End Sub
    8. End Class
    9. Public MustInherit Class Lebewesen
    10. Protected Alter As Integer
    11. Protected IQ As Integer
    12. Protected Sub New()
    13. End Sub
    14. Public MustOverride Sub Adaptivitaet() 'um auch ein Public MustOverride Sub drinzuhaben :-)
    15. End Class
    16. Public MustInherit Class Saeugetiere : Inherits Lebewesen
    17. Private kann_fliegen As Boolean
    18. Private hat_Fell As Boolean
    19. Private wie_viele_Zaehne As Integer
    20. Private Koerpertemperatur As Integer
    21. Public Sub New()
    22. MyBase.New()
    23. End Sub
    24. End Class
    25. Public MustInherit Class Paarhufer : Inherits Saeugetiere
    26. Public Structure Waffenarten
    27. Public Property hat_Hoerner As Boolean
    28. Public Property hat_Stosszaehne As Boolean
    29. Public Property hat_Klauen As Boolean
    30. Public Sub New(hatHoerner As Boolean, hatStosszaehne As Boolean, hatKlauen As Boolean)
    31. Me.hat_Hoerner = hatHoerner
    32. Me.hat_Stosszaehne = hatStosszaehne
    33. Me.hat_Klauen = hatKlauen
    34. End Sub
    35. End Structure
    36. Private ist_nachtaktiv As Boolean
    37. Public Sub New()
    38. MyBase.New()
    39. End Sub
    40. End Class
    41. Public MustInherit Class Echte_Schweine : Inherits Paarhufer
    42. Public Sub New()
    43. MyBase.New()
    44. End Sub
    45. End Class
    46. Public Class Hausschwein : Inherits Echte_Schweine
    47. Private dieses_wird_im_Stall_gehalten As Boolean
    48. Public Sub New()
    49. MyBase.New()
    50. End Sub
    51. Public Overrides Sub Adaptivitaet()
    52. 'Throw New NotImplementedException()
    53. End Sub
    54. End Class
    Bilder
    • BIld1 - Kopie.jpg

      91,18 kB, 994×398, 70 mal angesehen
    An die Neulinge: Nutzt Option Strict On und Option Infer Off. Dadurch kommt ihr mit Datentypumwandlungen nicht durcheinander und der Code verbessert sich um Einiges! Solche Fehler à la Dim Beispiel As Integer = "123" können nicht mehr passieren.
    Solange Du in die Konstruktoren (Sub New) nichts reinschreibst, kannst Du sie auch weglassen. Das muss nur explizit hingeschrieben werden, wenn was drinsteht. Und wenn eine abgeleitete Klasse darauf besteht, dass die Initialisierung, die die Basisklasse im Konstruktor mach, auch wirklich vorgenommen wird, dann ruft sie im eigenen Konstruktor MyBase.New auf, und zwar zwangsläufig als erste Konstruktoranweisung:

    Basisklasse macht im Konstruktor was, abgeleitete Klasse will auch, dass das gemacht wird:

    VB.NET-Quellcode

    1. Public MustInherit Class Lebewesen
    2. Protected Alter As Integer
    3. Protected IQ As Integer
    4. Public Sub New() 'muss NICHT Protected sein; dank MustInherit kann man den eh nicht von außen aufrufen
    5. Alter = 0
    6. End Sub
    7. Public MustOverride Sub Adaptivitaet() 'um auch ein Public MustOverride Sub drinzuhaben :-)
    8. End Class
    9. Public MustInherit Class Saeugetiere : Inherits Lebewesen
    10. Private kann_fliegen As Boolean
    11. Private hat_Fell As Boolean
    12. Private wie_viele_Zaehne As Integer
    13. Private Koerpertemperatur As Integer
    14. Public Sub New()
    15. MyBase.New()
    16. End Sub
    17. End Class


    Basisklasse macht nix im Konstruktor, abgeleitete Klasse auch nicht:

    VB.NET-Quellcode

    1. Public MustInherit Class Lebewesen
    2. Protected Alter As Integer
    3. Protected IQ As Integer
    4. Public MustOverride Sub Adaptivitaet() 'um auch ein Public MustOverride Sub drinzuhaben :-)
    5. End Class
    6. Public MustInherit Class Saeugetiere : Inherits Lebewesen
    7. Private kann_fliegen As Boolean
    8. Private hat_Fell As Boolean
    9. Private wie_viele_Zaehne As Integer
    10. Private Koerpertemperatur As Integer
    11. End Class


    Lebewesen sollte keinen IQ haben. Oder wie willst Du den bei der Pflanze oder einem Pilz berechnen? Spekulatius: Auch bei einem Axolotl wird das m.E. schwierig, da es, solange es im juvenilen Stadium bleibt, quasi ewig leben kann. Und da der IQ-altersabhängig ist …

    zu Deinen Fragen: Wie übergibst Du Parameter? Kommt drauf an. Eine Möglichkeit ist: Durch den Konstruktor:

    VB.NET-Quellcode

    1. Public Sub New(ÜbergebenesAlter As Integer, ÜbergebenerIQ As Integer)
    2. Me.Alter = ÜbergebenesAlter
    3. Me.IQ = ÜbergebenerIQ


    Warum sind in den Zwischenklassen viele Punkte Private? EchtesHausschwein kann dann weder die Daten direkt anschauen noch ändern. Absicht?

    Zur Frage 2: CreateInstance ist nicht nötig, verwende ich auch nicht. Das ist dann nötig, wenn Du keinen Konstruktor zu Verfügung stellen willst oder mit Singletons arbeitest (z.B.)., Ich selber nutze CreateInstance oder ähnliches nicht. Habe keinen Anwendungszweck.

    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „VaporiZed“ ()

    @VaporiZed Ok, danke Dir!
    IQ ist raus.
    Also wenn ich ein Hausschwein erstellen will, muss ich ja alle Daten festlegen. Mache ich das Klasse für Klasse (mit den jeweiligen Sub New()) oder sage ich einfach

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private HS As New Hausschwein(...,...,...)


    Warum sind in den Zwischenklassen viele Punkte Private
    Stimmt, mein Fehler. Sind jetzt Public
    An die Neulinge: Nutzt Option Strict On und Option Infer Off. Dadurch kommt ihr mit Datentypumwandlungen nicht durcheinander und der Code verbessert sich um Einiges! Solche Fehler à la Dim Beispiel As Integer = "123" können nicht mehr passieren.
    Die ganzen Daten, die Du für Hausschwein festlegen willst, kannst Du entweder alle festlegen, indem Du die Solldaten über den Konstruktor reinwirfst. Oder Hausschwein kümmert sich selber darum. Wenn die Daten (auch die in den Basisklassen) Public sind, kannst Du auch schreiben:

    VB.NET-Quellcode

    1. Dim MeinKleinesSchweinchen As New Hausschwein With {.Alter = 5, wie_viele_Zähne = 52, …}

    Wenn die Protected sind, dann

    VB.NET-Quellcode

    1. Dim MeinKleinesSchweinchen As New Hausschwein()
    und im Konstruktor

    VB.NET-Quellcode

    1. Public Sub New()
    2. Alter = 5
    3. wie_viele_Zaehne = 52
    4. End Sub

    oder z.B. auch mit Parametern

    VB.NET-Quellcode

    1. Public Sub New(GewünschtesAlter As Integer)
    2. Alter = GewünschtesAlter
    3. wie_viele_Zaehne = 52
    4. End Sub

    ach ja: wie_viele_Zaehne ist - wenn man von deutschen Wörtern in englischem Code mal absieht - ungünstig. Besser: Anzahl_der_Zähne oder Zahnanzahl.
    Alter ist quasi in Ordnung. Spätestens wenn es um andere Sachen geht, bei denen die Zahlen nicht für sich selbst sprechen*, dann besser z.B. KoerperlaengeInCm
    Aber das ist wieder ein anderes Thema.

    * bei Alter ist mir zumindest ziemlich klar, dass damit Alter in Jahren gemeint ist
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    VaporiZed schrieb:

    oder z.B. auch mit Parametern
    VB.NET-Quellcode
    Public Sub New(GewünschtesAlter As Integer)
    Alter = GewünschtesAlter
    wie_viele_Zaehne = 52
    End Sub
    ok, danke soweit.

    genau das: wie muss ich das aufrufen? Am besten alle Werte auf einmal übergeben.

    PS: auf 'Anzahl_der_Zaehne' geändert
    An die Neulinge: Nutzt Option Strict On und Option Infer Off. Dadurch kommt ihr mit Datentypumwandlungen nicht durcheinander und der Code verbessert sich um Einiges! Solche Fehler à la Dim Beispiel As Integer = "123" können nicht mehr passieren.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Bartosz“ ()

    Dim MeinKleinesSchweinchen As New Hausschwein(10)
    Da hilft Dir dann aber auch VisualStudio weiter, s. Anhang
    Bilder
    • WithALittleHelpFromMyIDE.png

      2,46 kB, 282×43, 73 mal angesehen
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Also in der letzten Klasse, ok. Übrigens, ich habe noch eine Klasse mehr gebraucht.

    Eine (vorerst) letzte Frage: Wie übergebe an Waffenarten neue Parameter? Weil hier sagt er, das ist kein Member:

    VB.NET-Quellcode

    1. Public Class Neues_Schwein : Inherits Hausschwein
    2. Public Sub New(


    VB.NET-Quellcode

    1. 'Option Strict On wurde in den Projekteigenschaften gesetzt.
    2. 'Assembly-Sprache ist Deutsch (Deutschland).
    3. Public Class Form1
    4. Private HS As New Neues_Schwein(10, False, False, 52, 36, False, False)
    5. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    6. Debug.WriteLine("")
    7. End Sub
    8. End Class
    9. Public MustInherit Class Lebewesen
    10. Protected Alter As Integer
    11. ' Basisklasse macht nix im Konstruktor, abgeleitete Klasse auch nicht:
    12. 'Public Sub New(uebergebenes_Alter As Integer) 'muss NICHT Protected sein; dank MustInherit kann man den eh nicht von außen aufrufen
    13. ' Alter = uebergebenes_Alter
    14. 'End Sub
    15. Public MustOverride Sub Adaptivitaet() 'um auch ein Public MustOverride Sub drinzuhaben :-)
    16. End Class
    17. Public MustInherit Class Saeugetiere : Inherits Lebewesen
    18. Public kann_fliegen As Boolean
    19. Public hat_Fell As Boolean
    20. Public Anzahl_der_Zaehne As Integer
    21. Public Koerpertemperatur As Integer
    22. 'Public Sub New()
    23. ' MyBase.New()
    24. 'End Sub
    25. End Class
    26. Public MustInherit Class Paarhufer : Inherits Saeugetiere
    27. Public Structure Waffenarten
    28. Public Property hat_Hoerner As Boolean
    29. Public Property hat_Stosszaehne As Boolean
    30. Public Property hat_Klauen As Boolean
    31. Public Sub New(hatHoerner As Boolean, hatStosszaehne As Boolean, hatKlauen As Boolean)
    32. Me.hat_Hoerner = hatHoerner
    33. Me.hat_Stosszaehne = hatStosszaehne
    34. Me.hat_Klauen = hatKlauen
    35. End Sub
    36. End Structure
    37. Public ist_nachtaktiv As Boolean
    38. 'Public Sub New()
    39. ' MyBase.New()
    40. 'End Sub
    41. End Class
    42. Public MustInherit Class Echte_Schweine : Inherits Paarhufer
    43. 'Public Sub New()
    44. ' MyBase.New()
    45. 'End Sub
    46. End Class
    47. Public Class Hausschwein : Inherits Echte_Schweine
    48. Public dieses_wird_im_Stall_gehalten As Boolean
    49. 'Public Sub New()
    50. ' MyBase.New()
    51. 'End Sub
    52. Public Overrides Sub Adaptivitaet()
    53. 'Throw New NotImplementedException()
    54. End Sub
    55. End Class
    56. Public Class Neues_Schwein : Inherits Hausschwein
    57. Public Sub New(
    58. uebergebenes_Alter As Integer,
    59. kann_fliegen As Boolean,
    60. hat_Fell As Boolean,
    61. Anzahl_der_Zaehne As Integer,
    62. Koerpertemperatur As Integer,
    63. ist_nachtaktiv As Boolean,
    64. dieses_wird_im_Stall_gehalten As Boolean)
    65. 'MyBase.New()
    66. Alter = uebergebenes_Alter
    67. Me.kann_fliegen = kann_fliegen
    68. Me.hat_Fell = hat_Fell
    69. Me.Anzahl_der_Zaehne = Anzahl_der_Zaehne
    70. Me.Koerpertemperatur = Koerpertemperatur
    71. Me.ist_nachtaktiv = ist_nachtaktiv
    72. Me.dieses_wird_im_Stall_gehalten = dieses_wird_im_Stall_gehalten
    73. End Sub
    74. Public Overrides Sub Adaptivitaet()
    75. 'Throw New NotImplementedException()
    76. End Sub
    77. End Class

    An die Neulinge: Nutzt Option Strict On und Option Infer Off. Dadurch kommt ihr mit Datentypumwandlungen nicht durcheinander und der Code verbessert sich um Einiges! Solche Fehler à la Dim Beispiel As Integer = "123" können nicht mehr passieren.
    1. Neues_Schwein: Was ist denn das für eine Hausschweinart? Eine neue? Denn das wird hier suggeriert. Es ist kein Hausschwein, sondern eine Unterart von Hausschwein. Ist das beabsichtigt?
    2. Solange diese Structure Waffenarten nur besteht, aber es in den Hausschweinklassen keine Variable vom Typ Waffenarten gibt, ist die Structure nutzlos. Wenn Du aber eine entsprechende Variable in der Hausschweinklasse (Public Waffenart As Waffenarten) hast, dann kannst Du schreiben:

      VB.NET-Quellcode

      1. Dim MeinSchwein As New Hausschwein()
      2. MeinSchwein.Waffenart = New Paarhufer.Waffenarten(False, False, False)

    3. Man sollte gewisse Sachen nicht über den Konstruktor einstellen können. Manche Sachen sollte die Klasse selber festlegen. Sonst haben wir irgendwann hochgefährliche, fliegende, nachtaktive Schweine, die mit einer Körpertemperatur von 0 K den Planeten vergletschern.
    4. nested structures wie Waffenarten - oder gar Structures allgemein - sind nur selten nützlich. Nutze sie nur, wenn Du weißt, dass eine Class Dir keinen Vorteil bringt.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    1.) Ich nutze wieder

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private S As New Hausschwein(10, False, False, 52, 36, False, False, False, False, False)


    Ich dachte vorhin kurz, ich muss eine Klasse Neues_Schwein schreiben, da ich nicht auf alles Zugriff hatte. Hat sich aber erledigt. Gut, dass du das nochmal erwähnst.

    2.) Geändert und läuft:

    VB.NET-Quellcode

    1. Public Class Hausschwein : Inherits Echte_Schweine
    2. Public dieses_wird_im_Stall_gehalten As Boolean
    3. Public Waffenart As Waffenarten
    4. Public Sub New(
    5. uebergebenes_Alter As Integer,
    6. kann_fliegen As Boolean,
    7. hat_Fell As Boolean,
    8. Anzahl_der_Zaehne As Integer,
    9. Koerpertemperatur As Integer,
    10. ist_nachtaktiv As Boolean,
    11. dieses_wird_im_Stall_gehalten As Boolean,
    12. hat_hoerner As Boolean,
    13. hat_Klauen As Boolean,
    14. hat_Stosszaehne As Boolean)
    15. 'MyBase.New()
    16. Alter = uebergebenes_Alter
    17. Me.kann_fliegen = kann_fliegen
    18. Me.hat_Fell = hat_Fell
    19. Me.Anzahl_der_Zaehne = Anzahl_der_Zaehne
    20. Me.Koerpertemperatur = Koerpertemperatur
    21. Me.ist_nachtaktiv = ist_nachtaktiv
    22. Me.dieses_wird_im_Stall_gehalten = dieses_wird_im_Stall_gehalten
    23. Me.Waffenart.hat_Hoerner = hat_hoerner
    24. Me.Waffenart.hat_Klauen = hat_Klauen
    25. Me.Waffenart.hat_Stosszaehne = hat_Stosszaehne
    26. End Sub


    3.)
    Sonst haben wir irgendwann hochgefährliche, fliegende, nachtaktive Schweine, die mit einer Körpertemperatur von 0 K den Planeten vergletschern.
    Ja, hmm, es gibt ja fliegende Säugetiere (Fledermaus, Flughund)... D.h. die Klasse Hausschwein soll das selbst regeln, ok. Ich schreib da mal 'was zu.

    4.) War nur zu Übungszwecken.
    An die Neulinge: Nutzt Option Strict On und Option Infer Off. Dadurch kommt ihr mit Datentypumwandlungen nicht durcheinander und der Code verbessert sich um Einiges! Solche Fehler à la Dim Beispiel As Integer = "123" können nicht mehr passieren.

    Bartosz schrieb:

    gibt ja fliegende Säugetiere
    Ja, aber mit Dim CreepyPig As New Hausschwein(999, True, True, 1024, -273, True, False, True, True, True) hab ich ein gruseliges und hochgefährliches Hausschwein. Daher sollte die Hausschweinklasse selber festlegen, dass es z.B. eine gewisse Körpertemperatur hat und nicht fliegen kann. Und diese Daten sollte man von außen auch nicht festlegen (Konstruktor) oder ändern (Methode oder gar direkter Zugriff auf die Variablen) können:

    VB.NET-Quellcode

    1. Public Class Hausschwein : Inherits Echte_Schweine
    2. Public dieses_wird_im_Stall_gehalten As Boolean
    3. Public Waffenart As Waffenarten
    4. Public Sub New(uebergebenes_Alter As Integer, dieses_wird_im_Stall_gehalten As Boolean)
    5. Alter = uebergebenes_Alter
    6. Me.kann_fliegen = False
    7. Me.hat_Fell = False 'naja, ist relativ mit den Borsten
    8. Me.Anzahl_der_Zaehne = 44
    9. Me.Koerpertemperatur = 39
    10. Me.ist_nachtaktiv = False
    11. Me.dieses_wird_im_Stall_gehalten = dieses_wird_im_Stall_gehalten
    12. Me.Waffenart = New Paarhufer.Waffenarten(False, False, False, False)
    13. End Sub

    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Das klappt alles wunderbar. Danke nochmals!

    Zwei Fragen noch zum Schluss: Muss ich irgendwas von Lebewesen bis Hausschwein disposen? Oder muss ich noch irgendwas beachten?
    Und: In der grauen Infobox ist neben dem Feld von Alter ein * zu sehen (siehe Anhang). Was bedeutet das? Wegen Protected?

    Erledigt ^^
    Bilder
    • Screenshot - Kopie.jpg

      49,91 kB, 643×234, 67 mal angesehen
    An die Neulinge: Nutzt Option Strict On und Option Infer Off. Dadurch kommt ihr mit Datentypumwandlungen nicht durcheinander und der Code verbessert sich um Einiges! Solche Fehler à la Dim Beispiel As Integer = "123" können nicht mehr passieren.
    Spekulatius: das Stern bedeutet: geerbt von einer Basisklasse

    Disposen ist für mich gleichbedeutend mit IDisposable implementieren. Das ist nur dann notwendig, wenn Du mit Objekten arbeitest, die nicht automatisch plattgemacht werden. Oder eben solche, die IDisposable selber implementieren. Wenn ich z.B. eine Klasse habe, die etwas in einer bestimmten Schriftart auf dem Bildschirm darstellt und daher eine Font erstellt und nutzt, solange es lebt, implementiere ich dafür auch IDisposable, damit es dann im Disposing-Teil die Font entsorgt. Genauso mit Streams oder ggf. auch COM-Objekten. Du siehst: Bei einfachen Klassen ist das nicht nötig. Erst wenn man Objekte nutzt, die man disposen kann (weil sie ein Dispose als Methode anbieten) oder die man entsprechend der Klassendoku disposen sollte.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.