Galileo Computing < openbook > Galileo Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.

Inhaltsverzeichnis
Vorwort zur 5. Auflage
1 Allgemeine Einführung in .NET
2 Grundlagen der Sprache C#
3 Klassendesign
4 Vererbung, Polymorphie und Interfaces
5 Delegates und Ereignisse
6 Weitere .NET-Datentypen
7 Weitere Möglichkeiten von C#
8 Auflistungsklassen (Collections)
9 Fehlerbehandlung und Debugging
10 LINQ to Objects
11 Multithreading und die Task Parallel Library (TPL)
12 Arbeiten mit Dateien und Streams
13 Binäre Serialisierung
14 Einige wichtige .NET-Klassen
15 Projektmanagement und Visual Studio 2010
16 XML
17 WPF – Die Grundlagen
18 WPF-Containerelemente
19 WPF-Steuerelemente
20 Konzepte der WPF
21 Datenbindung
22 2D-Grafik
23 ADO.NET – verbindungsorientierte Objekte
24 ADO.NET – Das Command-Objekt
25 ADO.NET – Der SqlDataAdapter
26 ADO.NET – Daten im lokalen Speicher
27 ADO.NET – Aktualisieren der Datenbank
28 Stark typisierte DataSets
29 LINQ to SQL
30 Weitergabe von Anwendungen
Stichwort

Buch bestellen
Ihre Meinung?

Spacer
<< zurück
Visual C# 2010 von Andreas Kühnel
Das umfassende Handbuch
Buch: Visual C# 2010

Visual C# 2010
geb., mit DVD
1295 S., 49,90 Euro
Rheinwerk Computing
ISBN 978-3-8362-1552-7
Pfeil 3 Klassendesign
Pfeil 3.1 Einführung in die Objektorientierung
Pfeil 3.1.1 Vorteile der objektorientierten Programmierung
Pfeil 3.2 Klassendefinition
Pfeil 3.2.1 Klassen in Visual Studio anlegen
Pfeil 3.2.2 Das Projekt »GeometricObjectsSolution«
Pfeil 3.2.3 Deklaration von Objektvariablen
Pfeil 3.2.4 Zugriffsmodifizierer einer Klasse
Pfeil 3.2.5 Splitten einer Klassendefinition mit »partial«
Pfeil 3.3 Arbeiten mit Objektreferenzen
Pfeil 3.3.1 Prüfen auf Initialisierung
Pfeil 3.3.2 Ein Objekt freigeben
Pfeil 3.3.3 Mehrere Referenzen auf ein Objekt
Pfeil 3.4 Referenz- und Wertetypen
Pfeil 3.5 Eigenschaften eines Objekts
Pfeil 3.5.1 Öffentliche Felder
Pfeil 3.5.2 Datenkapselung mit Eigenschaftsmethoden sicherstellen
Pfeil 3.5.3 Ergänzung der Klasse »Circle«
Pfeil 3.5.4 Lese- und schreibgeschützte Eigenschaften
Pfeil 3.5.5 Sichtbarkeit der Accessoren »get« und »set«
Pfeil 3.5.6 Unterstützung von Visual Studio 2010
Pfeil 3.5.7 Automatisch implementierte Eigenschaften
Pfeil 3.5.8 Vereinfachte Objektinstanziierung mit Objektinitialisierern
Pfeil 3.6 Methoden eines Objekts
Pfeil 3.6.1 Methoden mit Rückgabewert
Pfeil 3.6.2 Methoden ohne Rückgabewert
Pfeil 3.6.3 Methoden mit Parameterliste
Pfeil 3.6.4 Methodenüberladung
Pfeil 3.6.5 Variablen innerhalb einer Methode (Lokale Variablen)
Pfeil 3.6.6 Referenz- und Wertparameter
Pfeil 3.6.7 Zugriff auf private Daten
Pfeil 3.6.8 Namenskonflikte mit »this« lösen
Pfeil 3.6.9 Trennung von Daten und Code im Speicher
Pfeil 3.6.10 Methode oder Eigenschaft?
Pfeil 3.6.11 Methoden und Eigenschaften umbenennen
Pfeil 3.7 Konstruktoren
Pfeil 3.7.1 Konstruktoren bereitstellen
Pfeil 3.7.2 Parametrisierte Konstruktoren und die Objektinitialisierung
Pfeil 3.7.3 Konstruktoraufrufe
Pfeil 3.7.4 Definition von Konstruktoren
Pfeil 3.7.5 »internal«-Konstruktoren
Pfeil 3.7.6 »private«-Konstruktoren
Pfeil 3.7.7 Konstruktorenaufrufe umleiten
Pfeil 3.8 Der Destruktor
Pfeil 3.9 Konstanten in einer Klasse
Pfeil 3.9.1 Konstanten mit dem Schlüsselwort »const«
Pfeil 3.9.2 Schreibgeschützte Felder mit »readonly«
Pfeil 3.10 Statische Klassenkomponenten
Pfeil 3.10.1 Begrifflichkeiten
Pfeil 3.10.2 Statische Klassenvariable in der Klasse »Circle«
Pfeil 3.10.3 Klassenspezifische Methoden
Pfeil 3.10.4 Statische Konstruktoren (Klasseninitialisierer)
Pfeil 3.10.5 Statische Klassen
Pfeil 3.10.6 Stand der Klasse »Circle«


Galileo Computing - Zum Seitenanfang

3.10 Statische Klassenkomponenten Zur nächsten ÜberschriftZur vorigen Überschrift


Galileo Computing - Zum Seitenanfang

3.10.1 Begrifflichkeiten Zur nächsten ÜberschriftZur vorigen Überschrift

In der Klasse Circle sind bisher drei Eigenschaften definiert, die den Zustand eines Objekts dieses Typs beschreiben:

  • XCoordinate
  • YCoordinate
  • Radius

Jede Instanz der Klasse reserviert für ihre Daten einen eigenen Speicherbereich, der vollkommen unabhängig von den Daten anderer Objekte ist. Auch alle bisher implementierten Methoden sind an Objekte gebunden, da sie mit den Objektdaten arbeiten.

Was ist aber, wenn Felder oder Methoden benötigt werden, die für alle Objekte der Klasse Circle gleichermaßen gültig sein sollen, also ohne feste Bindung an ein bestimmtes, konkretes Objekt? Stellen Sie sich vor, Sie beabsichtigen, in der Klasse Circle einen Zähler zu implementieren, der die Aufgabe hat, die Gesamtanzahl der Circle-Objekte festzuhalten. Ein solcher Zähler entspricht der Forderung nach einer allgemeinen, objektunabhängigen Funktionalität.

Um den Objektzähler zu realisieren, brauchen wir aber ein Feld, losgelöst von jedem konkreten Objekt, das nur in einer festen Bindung zur Klasse Circle steht. Der Objektzähler wäre damit als eine gemeinsame Eigenschaft aller Objekte dieses Typs zu betrachten.

Probleme dieser Art (also allen typgleichen Objekten klassen-, aber nicht objektgebundene Elemente zur Verfügung zu stellen) werden von C# durch das reservierte Wort static gelöst. Bezogen auf die Forderung nach einem Objektzähler, könnte die Problemlösung wie folgt aussehen:


public class Circle {
  public static int CountCircles;
  ...
}

Als static deklarierte Felder sind nicht an ein bestimmtes Objekt gebunden, sondern gehören dem Gültigkeitsbereich einer Klasse an. Sie werden als Klassenvariablen bezeichnet. Demgegenüber werden an Objekte gebundene Variablen (Felder) als Instanzvariablen bezeichnet. In der Klasse Circle sind das _Radius, _XCoordinate und _YCoordinate.

Da Klassenvariablen unabhängig von jedem konkreten Objekt sind, ist es unzulässig, sie auf einer Objektreferenz aufzurufen. Stattdessen werden sie unter Angabe des Typbezeichners angesprochen. In der Klasse Circle müssen Sie demnach den Objektzähler mit


int x = Circle.CountCircles;

auswerten.

Nicht nur Felder, auch Methoden können static sein. Für den Aufruf einer Klassenmethode gilt wie für ein statisches Feld, dass vor dem Methodenbezeichner der Klassenname angegeben werden muss. Klassenmethoden wurden schon häufig in den Beispielcodes dieses Buches benutzt: Es sind die Methoden WriteLine und ReadLine, die von der Klasse Console bereitgestellt werden. Auch Main ist als static definiert.

Sind in einer Klasse sowohl statische als auch objektbezogene Eigenschaften und Methoden definiert, unterliegt der wechselseitige Zugriff der beiden Elementtypen den folgenden beiden Regeln:

  • Aus einer Instanzmethode heraus lassen sich Klassenvariablen manipulieren und Klassenmethoden aufrufen.
  • Der umgekehrte Weg, nämlich aus einer statischen Methode heraus auf Instanzeigenschaften und Instanzmethoden zuzugreifen, ist nicht möglich.

Galileo Computing - Zum Seitenanfang

3.10.2 Statische Klassenvariable in der Klasse »Circle« Zur nächsten ÜberschriftZur vorigen Überschrift

Für statische Felder gelten dieselben Regeln der Datenkapselung wie für Instanzvariablen. Eine Klassenvariable wie CountCircles sollte daher in derselben Weise gekapselt werden, um nicht mit dem objektorientierten Paradigma der Datenkapselung zu brechen. Dazu wird sie als private deklariert. Um den Zugriff von außerhalb sicherzustellen, implementieren wir in der Klasse Circle zusätzlich eine statische Eigenschaftsmethode. Damit eine Manipulation des Zählers von außen nicht möglich ist, muss die Eigenschaft durch Verzicht auf den set-Accessor schreibgeschützt sein.


public class Circle {
  // ---------- Statisches Feld --------------
  private static int _CountCircles;
  // ---------- Klasseneigenschaft ----------
  public static int CountCircles {
    get {return _CountCircles;}
  }
  ...
}

Nun enthält die Circle-Klasse den angestrebten Objektzähler. Allerdings ist die Klassendefinition noch unvollständig, denn es fehlt die Programmlogik, um den Zähler mit jeder neuen Objektinstanz zu erhöhen. Dazu bieten sich die Konstruktoren an. Hierbei nutzen wir das Prinzip der Konstruktorverkettung und erhöhen den Objektzähler nur im parameterlosen Konstruktor, der aus den beiden anderen Initialisierungsroutinen aufgerufen wird:


// ---------- Konstruktoren ----------
public Circle() {
  _CountCircles++;
}

public Circle(double radius) : this() {
  Radius = radius;
}

public Circle(double radius, int xPos, int yPos) : this(radius) {
  XCoordinate = xPos;
  YCoordinate = yPos;
}

Im Zusammenhang mit dem Objektzähler müssen wir uns natürlich auch Gedanken über die Reduzierung des Objektzählers machen. Dazu fällt uns sofort der Destruktor ein, der sich zu diesem Zweck zunächst sehr gut zu eignen scheint. Der Haken ist allerdings, dass Sie den Destruktor nicht aus dem Code heraus aufrufen können. Dafür ist der Garbage Collector verantwortlich. Wann der Garbage Collector aber seine Aufräumarbeiten durchführt, lässt sich nicht vorherbestimmen.

Eine zweite Variante wäre es, den Zähler beim expliziten Aufruf einer Objektmethode zu verringern. Die Garantie, dass diese Methode aufgerufen wird, haben Sie aber ebenfalls nicht. Somit ist auch dies keine Lösung der Problematik.

Beide zuvor genannten Varianten lassen sich auch kombinieren, um die Aktualität des Objektzählers bestmöglich zu gewährleisten. Das ist in unserem Fall die optimale Lösung unseres Zählerproblems, auch wenn wir damit auf ein neues Problem stoßen: Destruktor und Objektmethode müssen synchronisiert werden, damit der Zähler nicht zweimal reduziert wird. Wie dieser Lösungsansatz realisiert wird, werden Sie in Kapitel 4, »Vererbung, Polymorphie und Interfaces«, erfahren.


Galileo Computing - Zum Seitenanfang

3.10.3 Klassenspezifische Methoden Zur nächsten ÜberschriftZur vorigen Überschrift

Neben den statischen Klasseneigenschaften können auch klassenspezifische Methoden definiert werden. Klassenmethoden sind unabhängig von einer bestimmten Klasseninstanz und werden ebenfalls mit dem Modifizierer static gekennzeichnet. Typischerweise werden statische Methoden dort eingesetzt, wo nicht mit objektspezifischen Daten gearbeitet wird oder allgemeingültige Operationen angeboten werden sollen. Ein typischer Vertreter des .NET Frameworks ist die Klasse Math, die ausschließlich statische Methoden enthält.

In Circle wollen wir nun auch noch ein paar Klassenmethoden bereitstellen. Hier bietet es sich zunächst an, eine allgemeine GetArea-Methode und eine klassenspezifische Methode GetCircumference zu implementieren. Damit wird es dem Benutzer der Klasse ermöglicht, die Kreisfläche und den Kreisumfang eines x-beliebigen Kreises zu ermitteln, ohne dafür vorher ein Circle-Objekt zu erstellen.


public static double GetArea(double radius) {
  return Math.PI * Math.Pow(radius, 2);
}
public double GetCircumference(double radius) {
  return 2 * Math.PI * radius;
}

Beide Methoden haben allgemeingültigen Charakter, denn die erforderlichen Dateninformationen werden nicht aus dem Objekt bezogen, sondern über einen Parameter den Methoden mitgeteilt. Damit sind GetArea und GetCircumference nach den Regeln der Methodenüberladung korrekt implementiert, denn die Parameterlisten unterscheiden sich. Der Modifizierer static ist kein Kriterium, das bei der Bewertung, ob eine Methodenüberladung gültig ist oder nicht, eine Rolle spielt.

Darüber hinaus soll die Klasse Circle um die Methode Bigger ergänzt werden, die in der Lage ist, zwei Kreisobjekte miteinander zu vergleichen. Eine ähnliche Methode ist in Circle bereits enthalten, allerdings als Instanzmethode.


public static int Bigger(Circle kreis1, Circle kreis2) {
  if (kreis1.Radius < kreis2.Radius)
    return -1;
  else if (kreis1.Radius == kreis2.Radius)
    return 0;
  else
    return 1;
}


Galileo Computing - Zum Seitenanfang

3.10.4 Statische Konstruktoren (Klasseninitialisierer) Zur nächsten ÜberschriftZur vorigen Überschrift

Bei der Instanziierung einer Klasse wird ein Konstruktor aufgerufen. Auf Klassenbasis gibt es dazu ein Pendant, das als statischer Konstruktor oder statischer Initialisierer bezeichnet wird. Der statische Konstruktor ist eine an die Klasse gebundene Methode, die nur auf die statischen Mitglieder der Klasse Zugriff hat. Der Aufrufzeitpunkt ist zwar nicht bekannt, erfolgt aber auf jeden Fall, bevor das erste statische Member einer Klasse aufgerufen oder eine Instanz der Klasse erzeugt wird. Zudem wird der statische Konstruktor einer Klasse während eines Programmlaufs nur ein einziges Mal aufgerufen.

Die Definition des statischen Konstruktors in Circle sieht folgendermaßen aus:


static Circle() {...}

Beachten Sie, dass ein statischer Konstruktor keinen Zugriffsmodifizierer akzeptiert. Da ein statischer Konstruktor automatisch aufgerufen wird und niemals direkt, macht eine Parameterliste keinen Sinn – die runden Klammern sind daher grundsätzlich leer.

Statische Konstruktoren bieten sich an, um komplexe Initialisierungen vorzunehmen. Dabei könnte es sich beispielsweise um das Auslesen von Dateien oder auch um die Initialisierung statischer Arrays handeln.

Aufrufreihenfolge der Konstruktoren

Statische Klasseninitialisierer und Konstruktoren sind sich in der Funktionsweise ähnlich. Während ein Klasseninitialisierer Klassendaten bereitstellt, versorgen Konstruktoren die objektspezifischen Felder mit Daten. Sobald Sie eine Objektvariable deklarieren, wird der statische Konstruktor ausgeführt und erst danach der Standardkonstruktor. Im Bedarfsfall dürfen Sie also im Konstruktor Code implementieren, der die vorhergehende Initialisierung der statischen Klassenmitglieder voraussetzt.


Galileo Computing - Zum Seitenanfang

3.10.5 Statische Klassen Zur nächsten ÜberschriftZur vorigen Überschrift

Es gibt Klassen, die nur statische Mitglieder enthalten. Meistens handelt es sich dabei um Klassen, die allgemeingültige Operationen bereitstellen. In der .NET-Klassenbibliothek gibt es davon einige, System.Math gehört auch dazu. Typischerweise sind solche Klassen nicht instanziierbar. Vor .NET 2.0 wurde das durch einen als private deklarierten Konstruktor realisiert. Seit .NET 2.0 können Sie auch Klassen als static definieren, zum Beispiel:


public static class MathDefinitions {
  public static double Addition(params double[] values) {
    // Anweisungen
  }


  public static double Subtraktion(params double[] values) {
    // Anweisungen
  }
  ...
}

Wenn Sie static als Modifizierer einer Klasse angeben, müssen Sie die folgenden Punkte beachten:

  • Statische Klassen dürfen nur statische Klassenmitglieder veröffentlichen. Der Modifizierer static ist auch bei den Membern anzugeben.
  • Statische Klassen enthalten keine Konstruktoren und können deshalb auch nicht instanziiert werden. Der parameterlose Konstruktor ist implizit private.

Der Aufruf statischer Klassen erfolgt unter Angabe des Klassenbezeichners, beispielsweise mit:


MathDefinitions.Addition(2, 77, 99);


Galileo Computing - Zum Seitenanfang

3.10.6 Stand der Klasse »Circle« topZur vorigen Überschrift

Ehe wir uns im folgenden Kapitel den nächsten Themen widmen, wollen wir noch alle Codefragmente unserer Klasse Circle übersichtlich zusammenfassen.


// ------------------------------------------------------------------
// Beispiel: ...\Kapitel 3\GeometricObjectsSolution
// ------------------------------------------------------------------
public class Circle {
  // ---------- Felder -------------
  private double _Radius;
  public int XCoordinate { get; set; }
  public int YCoordinate { get; set; }
  // --------- Statisches Feld -----------
  private static int _CountCircles;
  // --------- Konstruktoren ---------------
  public Circle() {
    _CountCircles++;
  }
  public Circle(double radius) : this() {
    Radius = radius;
  }
  public Circle(double radius, int xPos, int yPos) :this(radius) {
    XCoordinate = xPos;
    YCoordinate = yPos;
  }
  // -------- Eigenschaftsmethoden ----------
  public double Radius {
    get { return _Radius; }
    set {
      if (value >= 0)
        _Radius = value;
      else
        Console.WriteLine("Unzulässiger negativer Radius.");
    }
  }
  // ---------- Klasseneigenschaft -----------------
  public static int CountCircles {
    get { return _CountCircles; }
  }
  // ---------- Instanzmethoden ----------
  public double GetArea() {
    return 3.14 * Math.Pow(Radius, 2);
  }
  public double GetCircumference() {
    return 2 * 3.14 * Radius;
  }
  public int Bigger(Circle kreis) {
    if (Radius < kreis.Radius)
      return -1;
    else if (Radius == kreis.Radius)
      return 0;
    else
      return 1;
  }
  public void MoveXY(int dx, int dy) {
    XCoordinate += dx;
    YCoordinate += dy;
  }
  public void MoveXY(int dx, int dy, int dRadius) {
    XCoordinate += dx;
    YCoordinate += dy;
    Radius += dRadius;
  }
  // -------- Klassenmethoden ------------
  public static double GetArea(int radius) {
    return 3.14 * Math.Pow(radius, 2);
  }   
  public  static double GetCircumference(double radius) {
    return 2 * 3.14 * radius;
  }
  public static int Bigger(Circle kreis1, Circle kreis2) {
    if (kreis1.Radius < kreis2.Radius)
      return -1;
    else if (kreis1.Radius == kreis2.Radius)
      return 0;
    else
      return 1;
  }
}



Ihr Kommentar

Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen. >> Zum Feedback-Formular
<< zurück
  Zum Katalog
Zum Katalog: Visual C# 2010

Visual C# 2010
Jetzt bestellen


 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchempfehlungen
Zum Katalog: Professionell entwickeln mit Visual C# 2012






 Professionell
 entwickeln mit
 Visual C# 2012


Zum Katalog: Windows Presentation Foundation






 Windows Presentation
 Foundation


Zum Katalog: Schrödinger programmiert C++






 Schrödinger
 programmiert C++


Zum Katalog: C++ Handbuch






 C++ Handbuch


Zum Katalog: C/C++






 C/C++


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo




Copyright © Rheinwerk Verlag GmbH 2010
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


Nutzungsbestimmungen | Datenschutz | Impressum

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de

Cookie-Einstellungen ändern