← Lekcje
PHP · lekcja 15

Programowanie obiektowe 3/3: public, private, protected

Dzisiaj:

  1. Trzy poziomy dostępu do właściwości i metod: public, private, protected
  2. Właściwość private jest widoczna tylko wewnątrz własnej klasy
  3. Publiczna metoda jako jedyna droga do prywatnej właściwości
  4. Ćwiczenie: private $price w class-product.php i metoda getPrice()
Rozgrzewka · 3 minuty

Rozgrzewka: __construct i __destruct

  1. Kiedy PHP wywołuje __construct()?
  2. Czy konstruktor jest obowiązkowy w każdej klasie?
  3. Kiedy PHP wywołuje __destruct()?
Część 1 · Trzy poziomy dostępu

Trzy poziomy dostępu: public, private, protected

Do tej pory każda właściwość klasy Product była public - widoczna wszędzie. PHP ma jeszcze dwa poziomy: private (widoczna tylko wewnątrz własnej klasy) i protected (widoczna w klasie i w klasach, które po niej dziedziczą - to temat spoza tej lekcji). To jak trzy poziomy dostępu w mieszkaniu: do salonu (public) wchodzi każdy, do pokoju rodzinnego (protected) tylko domownicy, do prywatnej szafki (private) tylko jej właściciel.

public dostęp: wszędzie ✓ w klasie ✓ poza klasą ✓ w klasach potomnych protected dostęp: klasa i potomne ✓ w klasie ✗ poza klasą ✓ w klasach potomnych private dostęp: tylko ta klasa ✓ w klasie ✗ poza klasą ✗ w klasach potomnych
PHP Manual: „Class members declared public can be accessed everywhere. Members declared protected can be accessed only within the class itself and by inheriting and parent classes. Members declared as private may only be accessed by the class that defines the member” · php.net/manual/en/language.oop5.visibility.php
Część 2 · Private z zewnątrz

private: błąd przy dostępie z zewnątrz

poza klasą Product $product1->price Fatal error: Uncaught Error Cannot access private property Product::$price
class Product {
    public $name;
    private $price;
    // ... __construct jak na lekcji poprzedniej
}

$product1 = new Product("Keyboard", 120);
echo $product1->name;   // Keyboard - działa, name jest public
echo $product1->price;  // Fatal error - price jest private

Ciekawostka z PHP Manual: reguła private nie blokuje dostępu między dwoma obiektami tej samej klasy. Wewnątrz metody klasy Product wolno odczytać price innego obiektu Product, mimo że jest private: PHP pilnuje granicy klasy, nie granicy pojedynczego obiektu.

PHP Manual: language.oop5.visibility.php · php.net/manual/en/language.oop5.visibility.php · ciekawostka: „Objects of the same type will have access to each others private and protected members even though they are not the same instances” · php.net/manual/en/language.oop5.visibility.php
Część 3 · Publiczna metoda jako droga do private

getPrice(): jedyna droga do prywatnej właściwości

bezpośrednio - zablokowane $product1->price przez metodę - działa $product1->getPrice() wewnątrz Product function getPrice() { return $this->price; 120
class Product {
    public $name;
    private $price;

    public function __construct($name, $price) { $this->name = $name; $this->price = $price; }

    public function getPrice() {
        return $this->price;
    }
}

$product1 = new Product("Keyboard", 120);
echo $product1->getPrice();  // 120
PHP Manual: language.oop5.visibility.php (metody i właściwości) · php.net/manual/en/language.oop5.visibility.php
Egzamin INF.03

Tak pytają na egzaminie

1. Do którego pola klasy Data możliwy będzie dostęp z zewnątrz poprzez nazwę obiektu utworzonego jako instancja tej klasy?

class Data {
  public $a;
  private $b;
  protected $c;
}
  1. Do wszystkich pól.
  2. Do pola $a.
  3. Do pola $b.
  4. Do pola $c.

2. Klasa Product ma private $price i publiczną metodę getPrice(), która zwraca $this->price. Który zapis NIE spowoduje błędu?

  1. echo $product1->price;
  2. echo $product1->getPrice();
  3. $product1->price = 10;
  4. print $product1->price;
CKE, EE.09, styczeń 2021, zadanie 3
Ćwiczenie przy komputerze · 20 minut

Ćwiczenie: private $price i getPrice() w class-product.php

  1. Otwórz class-product.php z folderu swojego serwera (np. htdocs) - plik z poprzedniej lekcji.
  2. Zmień public $price; na private $price; ($name zostaje public).
  3. W class Product dopisz metodę public function getPrice() { return $this->price; }.
  4. W liniach z echo zamień $product1->price i $product2->price na $product1->getPrice() i $product2->getPrice().
  5. Na chwilę dopisz echo $product1->price;, odśwież localhost/class-product.php i zobacz Fatal error w przeglądarce - potem usuń tę linię.
  6. Sprawdź stronę bez błędu - mają zostać te same dwie linie z nazwą i ceną co wcześniej.

Ma się pojawić: te same dwie linie z nazwą i ceną co na poprzednich lekcjach, tylko cena wychodzi teraz przez getPrice() - i chwilowy Fatal error w kroku 5, zanim go usuniesz.

Zasady pracowni
Na koniec

Sprawdź się

  1. Czym różni się public od private?
  2. Co się stanie, gdy spróbujesz odczytać właściwość private spoza klasy?
  3. Po co potrzebna jest metoda getPrice(), skoro $price jest teraz private?

To była ostatnia lekcja tematu programowania obiektowego - na następnej: przetwarzanie danych z formularza.

Poza szkołą

A jak to wygląda w produkcji?

Na lekcjiW produkcjiStatus
Właściwości oznaczone wprost public albo privateOd PHP 8.1 właściwość może być dodatkowo readonly - ustawiana raz w konstruktorze, potem nie do zmiany. Chroni to przed przypadkową zmianą danych po utworzeniu obiektu.nadal w użyciu (rosnąca popularność)
Dostęp do private $price tylko przez ręcznie napisaną metodę getPrice()Frameworki (np. Laravel) często generują takie metody automatycznie albo używają magicznych metod __get/__set, żeby nie pisać ich ręcznie dla każdej właściwości.nadal w użyciu
protected tylko wspomniany, bez przykładu z dziedziczeniemW kodzie produkcyjnym protected jest bardzo częste w klasach bazowych, po których dziedziczą inne klasy - to osobny temat (extends), poza zakresem tej lekcji.nadal w użyciu
PHP Manual: „As of PHP 8.1.0, a property can be declared with the readonly modifier, which prevents modification of the property after initialization” · php.net/manual/en/language.oop5.properties.php