CSharp Klassen (class)

Wir wollen in der objektorientierten Programmierung mit “Dingen” (= Objekte) arbeiten. Objekte sind Abstraktionen (Modelle) von Dingen, die es in der echten Welt gibt (ein Auto, ein Haus, eine Person, …).

In der OOP erstellen wir Objekte nicht einfach indem wir Einzelteile zusammensetzen. Stattdessen erstellen wir für jedes Objekt, das wir brauchen zuerst einen Bauplan. Der Bauplan legt fest wie ein Objekt aufgebaut ist, bzw. wie es erstellt werden kann. Wir nennen diesen Bauplan Klasse (class).

Eine Klasse kann unterschiedliche Arten von Bestandteilen enthalten. Die wichtigsten sind:

  • Daten
    Wir legen damit fest, welche Informationen ein Objekt speichern kann.
    Es gibt unterschiedliche Möglichkeiten das festzulegen.
    • Felder (Fields)
      sind einfache Variablen.
    • Eigenschaften (Properties)
      sind eine Möglichkeit besser zu steuern wer auf die Daten zugreifen kann und wie die Daten verändert und ausgelesen werden.
  • Logik (Methoden)
    Ein Objekt kann unterschiedliche Aktionen (Fähigkeiten) enthalten, die sie ausführen kann.
    Diese werden in Form von Methoden in der Klasse definiert.
  • Initialisierungslogik (Konstruktor)
    Das ist eine besondere Art einer Methode, die nur ausgeführt wird, wenn ein neues Objekt erstellt wird.
    Damit kann sichergestellt werden, dass das Objekt nach der Erstellung in einem sinnvollen Zustand und bereit für die Verwendung ist.

Beispiele

📘 Beispiel 1: Eine Klasse mit einem Feld

class Auto
{
    // Einfaches Feld (Variable innerhalb der Klasse)
    string marke;
}

📘 Beispiel 2: Eine Klasse mit einer Property

class Person
{
    // Property mit get und set
    // Ermöglicht kontrollierten Zugriff
    string Name { get; set; }
}

📘 Beispiel 3: Klasse mit Feld und Property

class Buch
{
    // Feld zur Speicherung der Seitenzahl
    int seiten;
 
    // Property – könnte später Logik enthalten
    string Titel { get; set; }
}

📘 Beispiel 4: Klasse mit einer Methode

class Hund
{
    // Methode beschreibt eine Fähigkeit des Objekts
    void Bellen()
    {
        // Logik der Methode
        Console.WriteLine("wau");
    }
}

📘 Beispiel 5: Klasse mit einem Konstruktor

class Fahrrad
{
    // Feld für die Farbe
    string farbe;
 
    // Konstruktor – wird beim Erstellen eines Objekts ausgeführt
    Fahrrad(string startFarbe)
    {
        // Initialisierung der Felder
        farbe = startFarbe;
    }
}

📘 Beispiel 6: Eine kombinierte Klasse mit allem

class Smartphone
{
    // Feld
    string modell;
 
    // Property
    int Speicher { get; set; }
 
    // Konstruktor
    Smartphone(string startModell, int startSpeicher)
    {
        modell = startModell;
        speicher = startSpeicher;
    }
 
    // Methode
    void Einschalten()
    {
        // Aktion des Objekts
        Console.WriteLine("🍎");
    }
}

Objekte (Instanzen)

Klassen für sich alleine können noch nicht verwendet werden. Da Klassen einem Bauplan entsprechen, können wir nicht im Bauplan schon Daten Speichern oder Funktionen (Methoden) aufrufen, sondern benötigen zuerst ein Objekt.

Mit der Klasse können jedoch sehr einfach Objekte erstellt werden. Dafür ist das Schlüsselwort new nötig. Das damit erstellte Objekt, kann dann in einer Variable gespeichert werden. Der Datentyp dieser Variable entspricht der Klasse des Objekts.

Anders gesagt: Klassen sind sowohl Baupläne (legen fest wie ein Objekt erstellt werden kann), als auch Datentypen (legen fest was ein Objekt kann).


Beispiel

// Definition
class Person
{
    // Property mit get und set
    // Ermöglicht kontrollierten Zugriff
    string Name { get; set; }
}
 
// Verwendung
Person p = new Person();

Durch new Person() wird ein neues Objekt der Klasse Person erstellt. Wir benötigen also das Schlüsselwort new vor dem Klassennamen, gefolgt von runden Klammern.

Die runden Klammern nach der Klasse werden benötigt, weil bei der Erstellung des Objekts immer auch der Konstruktor aufgerufen wird. Runde Klammern sind immer bei einem Methodenaufruf nötig, also auch beim Konstruktor.

Das erstellte Objekt wird über den Zuweisungsoperator = einer Variable mit dem Namen p zugewiesen. Der Datentyp der Variablen ist die Klasse Person.

Konstruktor

Der Konstruktor ist eine besondere Art einer Methode. Der Name des Konstruktors entspricht dem Namen der Klasse.

Ein Konstruktor hat keinen Rückgabewert (streng genommen ist der Rückgabewert das Objekt der Klasse selbst). Eine Klasse hat immer einen Konstruktor! Wenn kein Konstruktor vom Programmierer angegeben wurde, wird automatisch ein Konstruktor ohne Parameter erstellt.

Konstruktoren werden verwendet um die Objekte zu initialisieren. Wir machen sie somit bereit für die Verwendung. Meistens bedeutet das, dass Felder und/oder Properties sinnvolle Werte bekommen.

class Song 
{
	// Properties
	string Title { get; set; }
	int Duration { get; set; }
	
	// Konstruktor
	Song() {
		// Initialisierung
		Title = "Unbekannt";
		Duration = 0;
	}
}

Konstruktorenverkettung

Es können auch mehrere Konstruktoren definiert werden, die aufeinander aufbauen. So kann ein Konstruktor zu einem anderen Konstruktor weiterleiten und Parameter übergeben. Dieser könnte dann wieder an einen anderen Konstruktor weiterleiten usw.

class Song 
{
	// Properties
	string Title { get; set; }
	int Duration { get; set; }
	
	// Konstruktor ohne Parameter.
	// Nutzt Konstruktorverkettung um einen anderen Konstruktor mit zwei Parameter aufzurufen.
	Song() : this("Unbekannt", 0) {
	}
 
	// Konstruktor mit 2 Parameter
	Song(string title, int duration) {
		Title = title;
		Duration = duration;
	}
}

Methoden

Methoden sind Funktionen, die auf einem bestimmten Datentyp definiert sind. Klassen sind gleichzeitig auch Datentypen. Wird eine Methode in einer Klasse definiert, bedeutet das, dass nur Objekte dieser Klasse die Methode ausführen können.
Anders gesagt: Methoden legen fest, was ein Objekt tun kann.

Methoden bestehen aus:

  • der Signatur:
    • Rückgabedatentyp (Was bekommen wir von der Methode zurück, wenn sie fertig ist?)
    • Name (Wie heißt die Methode? Wird benötigt um sie aufzurufen.)
    • Parameter (Welche Werte (Argumente) werden der Methode übergeben?)
  • und dem Rumpf (Body):
    • Implementierung (Was macht die Methode?)

Parameter

  • Eine Methode kann keinen, einen, oder mehrere Parameter haben.
  • Mehrere Parameter sind mit Beistrich voneinander getrennt.
  • Jeder Parameter besteht aus dem Datentyp und dem Namen (Identifier).
  • Ein Parameter wird innerhalb der Methode wie eine Variable verwendet.

Rückgabewert

  • Jede Methode (ausgenommen der Konstruktor) hat einen Rückgabewert.
  • Bei der Methodensignatur muss der Datentyp des Rückgabewerts angegeben werden.
  • Der Rückgabewert kann vom Aufrufer der Methode ausgelesen werden.
  • Mit dem Schüsselwort return innerhalb der Methode wird der Rückgabewert festgelegt und die Methode beendet.
  • Bietet die Methode keinen Rückgabewert an, so muss trotzdem ein Datentyp angegeben werden.
    In diesem Fall kann void (= Leere, Nichts) angegeben werden.

Parameter und Rückgabewerte können wie Postfächer betrachtet werden:

  • Parameter
    Postfach der Methode von dort werden Werte abgeholt die zur Verarbeitung benötigt werden.
  • Rückgabewert
    Postfach des Aufrufers von dort werden Werte abgeholt, die die Methode zurücksendet.

Beispiele zu Methoden

Beispiel 1: Methode ohne Parameter, mit Rückgabewert

class Uhr
{
    string HoleZeit()
    {
        return "12:00";
    }
}
 
// Verwendung
Uhr u = new Uhr();
string zeit = u.HoleZeit();

Beispiel 2: Methode mit einem Parameter

class Mathe
{
    int Quadrat(int zahl)
    {
        return zahl * zahl;
    }
}
 
// Verwendung
Mathe m = new Mathe();
int q = m.Quadrat(5);

Beispiel 3: Methode mit mehreren Parametern

class Rechner
{
    int Addiere(int a, int b)
    {
        return a + b;
    }
}
 
// Verwendung
Rechner r = new Rechner();
int summe = r.Addiere(3, 7);

Beispiel 4: Methode mit void (kein Rückgabewert)

class Drucker
{
    void Drucken(string text)
    {
    }
}
 
// Verwendung
Drucker d = new Drucker();
d.Drucken("Hallo Welt!");

Beispiel 5: Verdeutlichung der Signatur

class Spieler
{
    string ErzeugeStatus(int punkte, int leben)
    {
        return "Punkte: " + punkte + ", Leben: " + leben;
    }
}
 
// Verwendung
Spieler s = new Spieler();
string status = s.ErzeugeStatus(120, 3);

Beispiel 6: Methode mit internem Ablauf vor return

class Temperatur
{
    double InFahrenheit(double celsius)
    {
        double ergebnis = celsius * 1.8 + 32;
        return ergebnis;
    }
}
 
// Verwendung
Temperatur t = new Temperatur();
double f = t.InFahrenheit(20.0);