Klasy

Klasy są podstawowymi typami referencyjnymi w C#.

Ogólna deklaracja klasy:

[modyfikatory]  class  nazwaKlasy   [ : nazwaNadklasy , interfejsy ]
{
   // Deklaracje składowych klasy
}

Przykładowo:


class  Przykład {
  int wartość ;	// deklaracja składowej
  public Przykład ( int wartość )  { 	// Konstruktor
     this.wartość = wartość ;
  }
} 

Dostępne modyfikatory dla klasy:
public : (ew. internal) modyfikuje dostęp do klasy. Domyślnie klasa jest prywatna.
sealed : powoduje, że z danej klasy nie można dziedziczyć. Np. sealed class A { ... }
abstract : tworzy klasę abstrakcyjną (mogącą zawierać metody abstrakcyjne). Przydatne przy dziedziczeniu.

this : słowo kluczowe oznaczające referencję do obiektu, z którego wywołano metodę (inaczej mówiąc – oznacza referencję do samego siebie). Oczywiście nie można używać this wewnątrz metod statycznych (one nie są wywoływane na rzecz obiektu).

base : słowo kluczowe pozwalające na odwołania do składowych klasy bazowej (oznacza referencję do obiektu klasy bazowej "zaszytego" w obiekcie, z którego wywołano metodę).

Konstruktor:

Konstruktor jest specjalną metodą (o nazwie identycznej z nazwą klasy) wywoływaną automatycznie podczas tworzenia egzemplarza klasy (ew. struktury). Konstruktor nie posiada typu zwracanej wartości (nie zwraca nawet void). Można przeciążać konstruktory – konstruktor nie pobierający żadnego argumentu jest konstruktorem domyślnym. Ponadto jeśli klasa nie definiuje żadnego konstruktora, to automatycznie jest dla niej tworzony konstruktor domyślny (inicjalizujący wszystkie pola domyślną wartością).

Np.

class A {
   public A() {...}  // Deklaracja konstruktora domyślnego
}

Konstruktor klasy pochodnej musi najpierw wywołać konstruktor klasy bazowej. W przypadku gdy klasa bazowa nie posiada konstruktora domyślnego, musimy jawnie wywołać jeden z jej konstruktorów. W tym celu używa się słowa kluczowego base .

Ponadto definiując metodę, możemy wskazać, aby przed jej wykonaniem został wywołany jeden z konstruktorów (uzyskujemy to poprzez zapisanie po dwukropku słowa kluczowego this w formie wywołania metody). Przykład:


class  MyClass : A {
  MyClass(int a): base(a){...} // Konstruktor wywołujący konstruktor nadklasy.
  MyClass(): this(0){...}      // Konstruktor domyślny, wywołujący
}                              //konstruktor z parametrem. 

Konstruktor może posiadać dowolny rodzaj dostępu.

Ponadto możliwe jest tworzenie konstruktorów statycznych (jednak taki konstruktor nie może pobierać żadnych parametrów, np.


class Witacz {
  public static Witacz() { System.Console.WriteLine("Witaj");
} 
Statyczny konstruktor wykonuje operacje potrzebne do inicjalizacji klasy. Statyczne konstruktory nie mogą być wywoływane bezpośrednio.


Destruktor:

Destruktor jest specjalną metodą (o nazwie ~NazwaKlasy) wywoływaną podczas usuwania obiektu z pamięci. Ma na celu posprzątanie po istnieniu obiektu danej klasy (np. zwolnienie zasobów systemowych). Należy jednak pamiętać, że w C# zwalnianiem nieużywanej pamięci zajmuje się system, a nie programista.

Np.


   public  class A {
      ...
      ~A( ) { ... }	 // Destruktor
   }

Destruktory nie są dziedziczone. Ponadto nie mogą pobierać żadnych parametrów. Nie określamy także zwracanej wartości ani specyfikatora dostępu. Destruktor jest wywoływany tylko automatycznie - nie można nakazać jego wywołania.

Destruktory są implementowane poprzez przeciążenie metody Finalize z klasy System.Object. Programy w C# nie mogą bezpośrednio przeciążać ani wywoływać metody Finalize.


Przeciążanie operatorów:

C# pozwala przeciążać operatory. Aby to zrobić definiujemy funkcję statyczną nazywającą się operator XX( ) gdzie w miejsce XX wstawiamy symbol jednego z przeciążalnych operatorów. Operatory, które można przeciążać to:

+   -   *   /   %   !   !=   ==   ~   <<   >>
<   <=   >   >=   &   |   ^   ++   --

Przykładowo:


class LZespol {
  double  Re, Im ;
  LZespol ( int r, int i ) { Re = r ; Im = i ; }          // Konstruktor
  public static LZespol operator + ( LZespol a, LZespol b) { // operator dodawania
    return  new LZespol ( a.Re+ b.Re , a.Im + b.Im );
  }
} 

Pomimo przeciążenia operatory zachowują swój priorytet (np. zawsze operator mnożenia * ma wyższy priorytet niż operator dodawania). Operatory * oraz & dają się przeciążać tylko w wersji dwuargumentowej.

Poza zwykłymi operatorami możemy także przeciążyć 'operatory' true oraz false .

Operatory && oraz || są automatycznie rozwijane z operatorów & i |, dlatego też nie muszą być przeciążane.

Operatory logiczne muszą być przeciążane 'parami'. To znaczy, że jeśli przeciążymy operator >, to musimy także przeciążyć operator < (pozostałe pary to == i != oraz <= i >= ).


prev | Strona Główna | next

Copyright © 2006 Daniel Dusiński
Wszelkie prawa zastrzeżone