Klasa to podstawowa konstrukcja logiczna, na której bazuje cały język C#, ponieważ to ona definiuje każdy obiekt i określa jego możliwości. Jedną z najważniejszych cech klasy jest to, że definiuje nowy typ danych. Jest to swoisty szablon pewnego obiektu, natomiast obiekt jest egzemplarzem klasy. Można powiedzieć że klasa opisuje w sposób abstrakcyjny parametry i funkcje konkretnych bytów.

Przykładowo gdyby tworzyć obiektową grę wyścigi, takimi bytami nazwiemy obiekty w grze, czyli Samochody i Tor wyścigowy. Jak z definicji wynika, obiekty te mogą posiadać różne parametry oraz funkcje, które są zdefiniowane w szablonie czyli klasie. W dalszej części rozdziału będziemy rozbudowywać nasze byty o nowe funkcje i parametry.

Deklaracja klasy i parametrów

edytuj

Zacznijmy od podstaw, czyli od deklaracji klasy oraz podstawowych parametrów. W naszym przykładzie będą dwie klasy Samochod oraz TorWyscigowy. Dla samochodu stworzymy 3 podstawowe parametry, czyli pojemność baku, prędkość maksymalna oraz prędkość aktualna. Natomiast tor będzie posiadał parametry tj. liczba aut na torze oraz samochód prowadzący. Oczywiście parametrów, można stworzyć nieskończenie wiele, natomiast dla przykładu taka liczba jest w zupełności wystarczająca.

class Pojazd
{
	double pojemnoscBaku;
	int predkoscMaksymalna;
	int predkoscAktualna;
}

class TorWyscigowy
{
        int liczbaAutNaTorze;
        Pojazd prowadzacy;
}

Nowo utworzone klasy definiują nam nowe typy danych. Są one takie same jak nazwa klasy, czyli Pojazd oraz TorWyscigowy. Istotną sprawą jest to, że sama definicja class nie tworzy jeszcze obiektu, jest to jedynie szablon.

Tworzenie obiektu

edytuj

Aby utworzyć egzemplarz klasy, czyli obiekt, należy wykonać poniższą instrukcję:

Pojazd auto1 = new Pojazd(); //Tworzy obiekt klasy Pojazd o nazwie auto1
Pojazd auto2 = new Pojazd(); //Tworzy inny obiekt klasy Pojazd o nazwie auto2

Dostęp do obiektu

edytuj

Na początku definiując klasę, zdefiniowaliśmy kilka parametrów początkowych. Aby dostać się do parametrów (również do metod) wykorzystuje się operator kropki [.], operator ten łączy nazwę obiektu z nazwą składowej.

auto1.predkoscMaksymalna = 180;
auto2.predkoscMaksymalna = 210;

Metody klasy

edytuj

Oprócz parametrów klasy, można tworzyć również metody. Określają one w pewnym sensie funkcje danego obiektu. Tak również jest w świecie rzeczywistym, auto oprócz parametrów tj. prędkość maksymalna czy pojemność baku, posiada funkcje przyśpieszania, zwalniania itd. W podobny sposób można opisać tor wyścigowy.

class Pojazd
{
    public double pojemnoscBaku;
    public int predkoscMaksymalna;
    public int predkoscAktualna;

    public void przyspiesz(int predkosc)
    {
        this.predkoscAktualna += predkosc;
    }

    public void zwolnij(int predkosc)
    {
        this.predkoscAktualna -= predkosc;
    }
}

class TorWyscigowy
{
    public int liczbaAutNaTorze;
    public Pojazd prowadzacy;

    public void dodajSamochodDoWyscigu()
    {
        liczbaAutNaTorze++;
    }

    public void zmienProwadzacego(Pojazd prowadzacy)
    {
        this.prowadzacy = prowadzacy;
    }
}

Poniżej przykład wykorzystania utworzonych klas, czyli symulacja wyścigu

//Zadeklarowanie nowych obiektów w grze
Pojazd auto1 = new Pojazd();
Pojazd auto2 = new Pojazd();
TorWyscigowy tor = new TorWyscigowy();

//Dodadnie dwóch samochodów do wyścigu
tor.dodajSamochodDoWyscigu();
tor.dodajSamochodDoWyscigu();

//Zmiana prędkości samochodów
auto1.przyspiesz(100);
auto2.przyspiesz(120);

//auto2 jedzie szybciej od auto1 wiec to ono obejmuje prowadzenie
tor.zmienProwadzacego(auto2);

//Statystyki wyścigu
Console.WriteLine("Na torze jest: " + tor.liczbaAutNaTorze + " samochodów.");
Console.WriteLine("Aktualna prędkość auta prowadzącego w wyścigu wynosi: " + tor.prowadzacy.predkoscAktualna);

Konstruktor

edytuj

Inicjalizacja wszystkich zmiennych po kolei, podczas tworzenia nowego obiektu, jest zajęciem uciążliwym. Już nie wspominając o inicjalizacji kilkunastu obiektów z kilkoma parametrami. Aby ułatwić te zadania, stworzono narzędzie jakimi są konstruktory. Jak z samej nazwy można wywnioskować, konstruktor, to narzędzie do konstruowania obiektu. Co za tym idzie jest wywoływany podczas inicjalizacji. Tak więc każda klasa musi zawierać konstruktor. No dobrze, ktoś by zapytał dlaczego w powyższych przykładach brakuje konstruktora? Odpowiedź jest prosta, jeśli nie napiszemy żadnego konstruktora, to C# sam sobie stworzy, w domyśle, pusty konstruktor. Możemy się o tym przekonać podczas inicjalizacji obiektu, ponieważ po słowie kluczowym new wywołujemy konstruktor domyślny:

Pojazd auto1 = new Pojazd();

Analizując powyższy fragment kodu, można zauważyć że konstruktor jest podobny do metody, o takiej samej nazwie co klasa. Od metody różni się tym, że nie może zwracać żadnych wartości. Poniższy przykład pokazuje jak należy definiować konstruktor podstawowy inicjalizujący wybrane parametry.

class Pojazd
{
    public double pojemnoscBaku;
    public int predkoscMaksymalna;
    public int predkoscAktualna;

    public Pojazd()
    {
        this.predkoscMaksymalna = 200;
        this.pojemnoscBaku = 50.0;
    }
}

Konstruktor sparametryzowany

edytuj

Wcześniej omawialiśmy konstruktor prosty, który umożliwia nam inicjalizacje parametrów; jednak takie przypisywanie wartości nie jest zbyt uniwersalnym rozwiązaniem, ponieważ każdorazowe utworzenie obiektu nadaje takie same parametry. W celu lepszej kontroli nad inicjalizacją utworzymy konstruktor sparametryzowany. Podczas tworzenia nowego konstruktora, skorzystamy z możliwości przeciążania metod.

class Pojazd
{
    public double pojemnoscBaku;
    public int predkoscMaksymalna;
    public int predkoscAktualna;

    public Pojazd()
    {
        this.predkoscMaksymalna = 200;
        this.pojemnoscBaku = 50.0;
    }

    public Pojazd(int predkoscMaksymalna, double pojemnoscBaku)
    {
        this.predkoscMaksymalna = predkoscMaksymalna;
        this.pojemnoscBaku = pojemnoscBaku;
    }
}

Nowy konstruktor przyjmuje dwa parametry, a następnie przekazuje je do parametrów globalnych, oznaczonych słówkiem kluczowym this. Poniżej przykład zastosowania obu konstruktorów. Na koniec jeszcze dodam wzmiankę, że konstruktorów możemy tworzyć nieskończenie wiele. Jest tylko jedno ograniczenie, każdy nowy konstruktor musi przyjmować inne parametry, od istniejących konstruktorów. Podczas inicjalizacji odpowiedni konstruktor jest wybierany automatycznie, poprzez dopasowanie typów i ilości przekazywanych parametrów.

//Wykorzystujemy konstruktor domyślny
Pojazd auto1 = new Pojazd();

//Wykorzystujemy konstruktor sparametryzowany
Pojazd auto2 = new Pojazd(150, 45.0);

Słowo kluczowe this

edytuj

Słowo kluczowe this umożliwia metodzie odwołanie się do obiektu który ją wywołał. W powyższych przykładach wykorzystywaliśmy słowo kluczowe this przed nazwą parametru, aby zaznaczyć, że odwołujemy się do parametrów globalnych aktualnego obiektu. Tak na prawdę użycie słówka kluczowego this nie jest wymagane - poza jedną sytuacją. Chodzi o ukrywanie zmiennych składowych. W przykładzie z konstruktorem sparametryzowanym dla zachowania spójności nazw zastosowaliśmy takie same nazwy parametrów konstruktora, jak parametry globalne. W tym przykładzie słowem kluczowym this oznaczamy parametry globalne, natomiast parametry bez słowa kluczowego this odwołują się do parametrów konstruktora.

Poprzedni rozdział: Typy danych
Następny rozdział: Operatory