Konstruktor i Destruktor

Konstruktor

Konstruktor jest to specjalna metoda która wywoływana jest podczas tworzenia obiektu.

Metoda konstruktora musi nazywać się __construct. Pobiera dowolną ilość argumentów jednak nie może nic zwracać.

Klasa nie musi zawierać konstruktora (te z poprzednich przykładów nie posiadały). Jednak gdy klasa posiada konstruktor, podczas tworzenia obiektów należy podać argumenty, które zostaną przesłane do konstruktora.


<?php
class Traba{
    public function __construct( $dlugosc ){
        $this->dlugoscTraby = $dlugosc;
    }
    private $dlugoscTraby;
}
class Slon{
    private $imie;
    private $traba;
    public function _construct( $imie,$dlugosc ){ //2
        $this->imie = $imie;
        $this->traba = new Traba($dlugosc);  //3
    }
    
    }

}
$dumbo = new Slon('dumbo',2);  //1

?>

//1 Tworzymy obiekt klasy Slon, klasa ta posiada konstruktor który wywolywany jest automatycznie, argumenty podajemy w nawiasach.

//2 Konstruktor przypisuje wartosc do właściwości $imie, następnie //3 tworzy obiekt klasy Traba, wywolujac jej konstruktor.

Domyślny konstruktor jest to konstruktor nie pobierający argumentów lub którego wszystkie argumenty są domiemane, podczas tworzenia obiektu możemy pominąć nawiasy.


<?php
class Domyslny{
    private $cecha1;
    private $cecha2;
    public function __construct($cecha1=0, $cecha2=10){
    $this->cecha1 = $cecha1;
    $this->cecha2 = $cecha2;
    }
}
$obiekt1 = new Domyslny; // mozemy pominac nawiasy
$obiekt2 = new Domyslny(2,2); // badz wprowadzic inne
                             // wartosci niz domyslne
 ?>    

Przeciążanie konstruktorów

W PHP nie ma możliwości przeciążania konstruktorów -jednak można osiągnąć podobny rezultat.

Przykładowo tworzymy obiekt klasy odcinek podając współrzędne punktu końcowego. Bądź podając długość odcinka, w takim przypadku odcinek leżeć będzie na osi OX.


<?php
class odcinek{
private $koniec;
function __construct(){
if(func_num_args() == 2){
    $koniec = array(
                'x' => func_get_agr(0), 
                'y' => func_get_agr(1),
                );
    }
elseif(func_num_args() == 1) {
    $koniec = array(
                'x' => func_get_agr(0), 
                'y' => 0,
                );
    }
  }
}
?>

Destruktor

Destruktor jest to metoda wywoływana automatczynie gdy obiekt danej klasy jest usuwany.

Metoda destruktora nosi nazwę _destruct(), nie może ona pobierać argumentów ani zwracać.

Klasa nie musi posiadać destruktora, jest on wymagany gdy obiekt kończąc działanie zwalnia zarezerwowane zasoby, bądź informuje o informuje o tym fakcie.

Obiekty są kasowne przy wyjściu z zakresu (w tm przypadku na końcu skryptu). Obiekt można kasować samodzielnie przy użyciu funkcji unset(). Pobiera ona jako argument referencję do obiektu który chcemy skasować.

Gdy obiekt ginie, giną wraz z nim obiekty agregowane. Najpierw wywoływany jest destruktor obiektu a następnie destruktory obiektów agregowanych.


<?php
class DomekZkart{
    function __destruct(){
        echo 'runal domek  z kart';
    }
}
$domek = new DomekZkart;
unset($domek);
?>

Po wywołaniu powyższego skryptu ujrzymy na ekranie napis - 'runal domek z kart'

W lekcji "Klasy i obiekty" w części "Praktyka" stworzyliśmy klasę odpowiedzialną za połączenie z bazą danych. Niestety za każdym razem gdy ją tworzymy musimy wykonywać metodę connect, a na zakończenie pracy musimy pamiętać o disconnect. Teraz gdy poznaliśmy konstruktor i destruktor możemy sobie to ułatwić. Najprościej będzie poprostu zmienić nazwy metod: z connect na __construct i z disconnect na __destruct.


<?php
class db_mysql {
    private $connect 	= NULL;
    private $limit      = 10;

    public function __construct($host, $login, $pass)
    {
        $this->connect = mysql_connect(
                                $host, 
                                $login, 
                                $pass);
        if ($this->connect)
           mysql_select_db($database, $this->connect);
    }

    public function __destruct()
    {
        if(is_resource($this->connect)) {
            mysql_close($this->connect);
        }
    }

    public function selectAll($table, $limit = null, )
    {
        if (!$this->connect) return false;

        if ($limit === null || $limit > $this->limit) 
        {
            $limit = $this->limit;
        }
        $result = (
        mysql_query(
         "SELECT * FROM ".$table." LIMIT ".$limit
        ));
        while ($row = mysql_fetch_assoc($result)) {
            $a[] = $row;
		}
        return $a;
    }
};

$mysql = new db_mysql('localhost', 'test', 'root', '1234');
print_r($mysql->selectAll('answer', 30));
?>    

Proszę zwrócić uwagę jak teraz wygląda wykorzystanie naszej klasy. Zamiast 3 linijek mamy wszystko w 1. Na tym przykładzie widzimy z tego małe korzyści, ale przy większych projektach takie rozwiązanie jest bardzo wygodne. Pewna część czynności jest wykonywana automatycznie, nie musimy o nich pamiętać. Tworząc obiekt automatycznie łączymy się z bazą, a gdy go usuwamy to następuje rozłączenie z bazą. Zmniejsza to ryzyko wystąpienia błędu.