Języki Programowania – Zajęcia 5

Klasy i obiekty – pola i metody

Cel zajęć

Dzisiaj poznamy klasy i obiekty w C++. Nauczymy się tworzyć własne typy danych, przechowywać informacje w polach oraz wykonywać operacje za pomocą metod. Omówimy też, jak kontrolować dostęp do danych przy użyciu public i private.

1. Czym jest klasa i obiekt?

Klasa definiuje własny typ danych. Opisuje, jakie informacje obiekt przechowuje oraz jakie operacje można na nich wykonać. Obiekt jest konkretnym egzemplarzem klasy.

class Punkt {
public:
    double x;
    double y;
};

Klasa Punkt opisuje punkt o współrzędnych x i y. Średnik po zamykającej klamrze jest wymagany.

Obiekty utworzone na podstawie klasy można przekazywać do funkcji jako argumenty, podobnie jak zwykłe zmienne.

Punkt p1;
Punkt p2;

p1.x = 2.5;
p1.y = 4.0;
p2.x = -1.0;
p2.y = 3.0;

cout << p1.x << ", " << p1.y << endl;
cout << p2.x << ", " << p2.y << endl;

Każdy obiekt ma własne wartości pól. Zmiana p1.x nie zmienia wartości p2.x.

2. Pola klasy

Pola to zmienne zadeklarowane w klasie. Przechowują informacje opisujące obiekt. Mogą mieć różne typy, np. int, double, bool oraz string.

class Osoba {
public:
    string imie;
    int wiek;
    double wzrost;
    bool aktywna;
};

W tym przykładzie obiekt klasy Osoba może przechowywać imię, wiek, wzrost i informację logiczną. Na początku pola są publiczne, aby pokazać podstawowy sposób dostępu.

Ćwiczenie – klasa Samochod

Utwórz klasę Samochod, która będzie przechowywać podstawowe informacje o samochodzie. Na tym etapie nie pisz własnych konstruktorów.

  1. Dodaj pola marka i model typu string.
  2. Dodaj pole rokProdukcji typu int oraz pole przebieg typu double.
  3. Utwórz obiekt klasy Samochod w funkcji main().
  4. Przypisz polom przykładowe wartości.
  5. Wypisz wszystkie informacje o samochodzie na ekranie.

3. Metody klasy

Metoda to funkcja należąca do klasy. Zwykłą metodę wywołujemy na obiekcie tej klasy. Może ona korzystać z pól tego konkretnego obiektu i zmieniać ich wartości, jeśli pozwala na to jej definicja.

#include <iostream>
using namespace std;

class Punkt {
public:
    double x;
    double y;

    void przesun(double dx, double dy) {
        x += dx;
        y += dy;
    }

    void wypisz() {
        cout << x << ", " << y << endl;
    }
};

int main() {
    Punkt p1;
    p1.x = 0;
    p1.y = 0;

    Punkt p2;
    p2.x = 10;
    p2.y = 10;

    p1.przesun(2, 3);
    p1.wypisz();  // 2, 3
    p2.wypisz();  // 10, 10
}

Metoda przesun() zmienia współrzędne obiektu, na którym została wywołana. W tym przykładzie zmienia p1, ale nie zmienia p2.

3.1. Metoda zwracająca wynik

Metoda może zwracać wartość tak jak zwykła funkcja. Typ przed nazwą metody określa, jaki wynik zwraca.

class Punkt {
public:
    double x;
    double y;
    double roznica() {
        return ( x-y );
    }
};

Punkt p;
p.x = 4;
p.y = 3;
cout << p.roznica();  // 1

3.2. Wskaźnik this

W zwykłej, niestatycznej metodzie dostępny jest wskaźnik this, który wskazuje na obiekt, na którym aktualnie wykonuje się metoda. Przydaje się m.in. wtedy, gdy parametr i pole mają tę samą nazwę.

class Punkt {
private:
    double x;

public:
    void ustawX(double x) {
        this->x = x;
    }
};

this->x oznacza pole bieżącego obiektu, a samo x oznacza parametr metody. Operator -> służy do dostępu do składowych za pomocą wskaźnika.

4. Dostęp do pól i metod: public i private

Poziomy dostępu określają, z których miejsc programu można korzystać z elementów klasy.

W klasie elementy są domyślnie prywatne. Pola prywatne pomagają chronić dane przed przypadkową lub niepoprawną zmianą. Dostęp do nich można udostępniać przez publiczne metody.

class Ksiazka {
private:
    string tytul = "brak";
    string autor = "brak";
    int liczbaStron = 0;

public:
    void ustawDane(string t, string a, int strony) {
        tytul = t;
        autor = a;
        liczbaStron = strony;
    }

    void wypisz() {
        cout << "Tytul: " << tytul << endl;
        cout << "Autor: " << autor << endl;
        cout << "Liczba stron: " << liczbaStron << endl;
    }
};

Ksiazka k;
k.ustawDane("Hobbit", "J.R.R. Tolkien", 310);
k.wypisz();

Wynik:

Tytul: Hobbit
Autor: J.R.R. Tolkien
Liczba stron: 310

Nie możemy bezpośrednio zmienić pola, np. k.tytul = "Hobbit";, ponieważ jest ono prywatne (private). Zamiast tego korzystamy z publicznej metody ustawDane(), która zapisuje informacje o książce. Metoda wypisz() pozwala wyświetlić dane obiektu.

4.1. Gettery i settery

Getter to metoda zwracająca wartość pola, często nazwana getNazwa(). Setter to metoda ustawiająca wartość pola, często nazwana setNazwa(). Settery mogą również od razu sprawdzać, czy nowa wartość jest poprawna.

class Produkt {
private:
    double cena = 0.0;

public:
    double getCena() const {
        return cena;
    }

    void setCena(double nowaCena) {
        if (nowaCena >= 0) {
            cena = nowaCena;
        }
    }
};

Metoda getCena() odczytuje cenę, a setCena() zmienia ją tylko wtedy, gdy wartość nie jest ujemna. Słowo const przy getterze oznacza, że metoda nie zmienia stanu obiektu.

Wskazówka: Nie każde pole musi mieć setter. Jeżeli wartość nie powinna być zmieniana z zewnątrz, można udostępnić tylko getter albo metodę wykonującą kontrolowaną operację.

Ćwiczenie 2 – pola prywatne i metody

Dodaj do klasy Samochod prywatne pole typu string przechowujące nazwisko właściciela. Dodaj metody do wypisania i ustawienia tej zmiennej.

5. Najważniejsze informacje