W budowie
Materiał edukacyjny · Informatyka Podstawy paradygmatu obiektowego, cykl życia instancji i praca ze składowymi

CZĘŚĆ 22 · PROGRAMOWANIE OBIEKTOWE (OOP)

Klasy, obiekty, właściwości i konstruktor

PPrezentacja dla nauczyciela

W programowaniu proceduralnym kod składa się z oddzielnych zmiennych i operujących na nich funkcji. W miarę rozrostu projektu taki podział prowadzi do chaosu i trudności w utrzymaniu logiki. Programowanie zorientowane obiektowo (OOP) łączy dane (stan) oraz operacje na nich (zachowanie) w spójne całości zwane obiektami.

Klasa to wzorzec lub schemat, na podstawie którego tworzy się konkretne egzemplarze (instancje) w pamięci. W tej części poznasz fundamenty OOP w PHP:

  • Klasa a obiekt: Czym różni się definicja class Samochod od konkretnego obiektu utworzonego operatorem new.
  • Właściwości i metody: Jak deklarować pola przechowujące stan obiektu oraz funkcje wewnętrzne definiujące jego możliwości.
  • Pseudozmienna $this i operator ->: Jak wewnątrz metod odwoływać się do pól i metod bieżącej instancji (oraz dlaczego po strzałce nie podajemy znaku dolara).
  • Konstruktor __construct(): Magiczna metoda uruchamiana automatycznie w momencie tworzenia obiektu, służąca do wymuszenia podania niezbędnych danych początkowych.
  • Cykl życia obiektu i destruktor __destruct(): Moment zwalniania instancji z pamięci i porządkowanie zasobów.
  • Referencje a klonowanie: Dlaczego przypisanie $b = $a nie kopiuje obiektu oraz jak działa słowo kluczowe clone.

W emulowanym edytorze przeglądarkowym nie ma jeszcze pełnego środowiska wykonawczego dla obiektów PHP — dlatego zamiast ćwiczeń laboratoryjnych w Pracowni Web czeka na Ciebie 16 starannie opracowanych pytań quizowych, które gruntownie sprawdzą Twoją wiedzę i przygotują Cię do pytań teoretycznych na egzaminie zawodowym INF.03.

Klasa i obiekt

Klasa to przepis, a obiekt to konkretna rzecz zrobiona według tego przepisu. Klasę definiujemy słowem class, a obiekt tworzymy operatorem new.

W klasie umieszczamy właściwości (dane) i metody (funkcje). Do właściwości i metod obiektu odwołujemy się strzałką: $uczen->imie, $uczen->przedstaw().

Jeden przepis może opisywać wiele obiektów. Każdy obiekt ma własne wartości właściwości, mimo że korzysta z tych samych metod.

class Uczen {
    public $imie;
    public $punkty;

    public function przedstaw() {
        return $this->imie . ' ma ' . $this->punkty . ' pkt';
    }
}

$ola = new Uczen();
$ola->imie = 'Ola';
$ola->punkty = 18;
echo $ola->przedstaw();
1. Czym jest klasa?
2. Jak tworzymy obiekt?
3. Czym odwołujemy się do metody?

Właściwości i metody

Właściwości deklarujemy w klasie, najczęściej z modyfikatorem dostępu. Metody to funkcje w klasie; mają dostęp do właściwości przez $this, które oznacza „ten obiekt”.

Metoda może przyjmować parametry i zwracać wynik, tak jak zwykła funkcja. Dobrą praktyką jest jedna odpowiedzialność metody: albo liczy, albo wypisuje.

W klasie można też zdefiniować metodę __toString(), która pozwala wypisać obiekt przez echo. Bez niej PHP zgłosi błąd konwersji.

class Prostokat {
    public $bokA;
    public $bokB;

    public function pole() {
        return $this->bokA * $this->bokB;
    }

    public function obwod() {
        return 2 * ($this->bokA + $this->bokB);
    }
}

$p = new Prostokat();
$p->bokA = 4;
$p->bokB = 3;
echo 'Pole: ' . $p->pole() . ', obwod: ' . $p->obwod();
4. Co oznacza $this?
5. Do czego służy __toString()?
6. Co robi metoda w klasie?

Konstruktor i destruktor

Konstruktor __construct() wykonuje się automatycznie przy tworzeniu obiektu. W nim ustawiamy wartości początkowe, żeby obiekt nigdy nie był „pusty”.

Parametry konstruktora podajemy w nawiasach przy new: new Uczen('Ola', 18). To wygodniejsze niż ustawianie każdej właściwości osobno.

Destruktor __destruct() wykonuje się przy usuwaniu obiektu. Rzadko jest potrzebny — zwykle wystarczy konstruktor i zwykłe metody.

class Uczen {
    public $imie;
    public $punkty;

    public function __construct($imie, $punkty = 0) {
        $this->imie = $imie;
        $this->punkty = $punkty;
    }
}

$ola = new Uczen('Ola', 18);
$jan = new Uczen('Jan');
echo $ola->imie . ' ' . $ola->punkty . ' / ' . $jan->punkty;
7. Kiedy działa konstruktor?
8. Jak nazywa się konstruktor?
9. Po co wartości domyślne w konstruktorze?

Ćwiczenia — Quiz wiedzy o programowaniu obiektowym (16 pytań)

Ze względu na ograniczenia przeglądarkowego środowiska laboratoryjnego ta część skupia się na gruntownej weryfikacji wiedzy teoretycznej i analizie kodu. Zaznacz prawidłowe odpowiedzi w poniższych 16 pytaniach, a następnie kliknij przycisk na dole strony, aby sprawdzić swoje wyniki i zapisać postęp w kursie.

1. Jaka jest fundamentalna różnica między klasą a obiektem w języku PHP?
2. Wskaż poprawną składnię tworzenia nowej instancji klasy Uzytkownik w PHP:
3. Mając obiekt $produkt posiadający pole public $cena = 50;, który zapis poprawnie odczyta jego wartość?
<?php
class Towar {
    public $cena = 50;
}
$produkt = new Towar();
?>
4. Czym jest pseudozmienna $this w metodach klasy PHP?
5. Jaki tekst pojawi się na ekranie po uruchomieniu poniższego kodu?
<?php
class Samochod {
    public function __construct(string $marka) {
        echo "Tworzę: " . $marka . " | ";
    }
}

$s1 = new Samochod("Audi");
$s2 = new Samochod("BMW");
?>
6. Co oznacza poniższy zapis konstruktora wprowadzony w PHP 8.0?
<?php
class Uzytkownik {
    public function __construct(public string $login, public int $wiek) {}
}
?>
7. Kiedy w cyklu życia obiektu PHP wykonywana jest metoda __destruct()?
8. Jaki wynik zwróci poniższy kod?
<?php
class Konto {
    public int $saldo = 100;
}

$k1 = new Konto();
$k2 = new Konto();

$k1->saldo += 50;

echo $k1->saldo . " i " . $k2->saldo;
?>
9. Co stanie się po wykonaniu poniższego fragmentu kodu?
<?php
class Gracz {
    public int $punkty;
}

$g = new Gracz();
$g->punkty = ["złoto", "srebro"];
?>
10. Jaki wynik wyświetli poniższy kod?
<?php
class Klient {
    public string $imie = 'Anna';
}

$k1 = new Klient();
$k2 = $k1;
$k2->imie = 'Ewa';

echo $k1->imie;
?>
11. Aby utworzyć niezależną kopię obiektu, w której modyfikacje nie wpływają na oryginał, należy użyć:
<?php
class Adres {
    public string $miasto = 'Warszawa';
}

$oryginal = new Adres();
$kopia = clone $oryginal;
$kopia->miasto = 'Kraków';

echo $oryginal->miasto;
?>
12. Jaki będzie wynik porównania obiektów $a i $b w poniższym kodzie?
<?php
class Punkt {
    public function __construct(public int $x, public int $y) {}
}

$a = new Punkt(10, 20);
$b = new Punkt(10, 20);

var_dump($a == $b);
var_dump($a === $b);
?>
13. Jaki ciąg znaków wypisze poniższa pętla operująca na tablicy obiektów?
<?php
class Osoba {
    public function __construct(public string $imie, public string $nazwisko) {}
    public function formatuj(): string {
        return $this->nazwisko . " " . $this->imie[0] . ".";
    }
}

$ludzie = [
    new Osoba("Adam", "Kowalski"),
    new Osoba("Bartosz", "Nowak")
];

foreach ($ludzie as $osoba) {
    echo $osoba->formatuj() . " | ";
}
?>
14. Jaki będzie skutek próby odczytania właściwości $tytul w poniższym kodzie?
<?php
class Ksiazka {
    public string $tytul;
}

$k = new Ksiazka();
echo $k->tytul;
?>
15. Co umożliwia zwrócenie instrukcji return $this; na końcu metody klasy?
<?php
class BuforTekstu {
    private string $tekst = "";
    public function dodaj(string $t): self {
        $this->tekst .= $t;
        return $this;
    }
}
?>
16. Wskaż błąd logiczny/składniowy w poniższej metodzie zatankuj:
<?php
class Samolot {
    public int $paliwo = 100;

    public function zatankuj(int $litry): void {
        $paliwo += $litry;
    }
}
?>