Witaj, Gościu O nas | Kontakt | Mapa
Wortal Forum PHPEdia.pl Planeta Kubek IRC Przetestuj się!

Programowanie obiektowe dla początkujących

"Metody magiczne"

W php5 wprowadzono również tak zwane metody magiczne. Ich nazwy zaczynają się od podwójnego podkreślenia. "Metody magiczne" nie są jawnie wywoływane, lecz są wywoływane automatycznie na skutek pewnego działania. Można powiedzieć, że poznaliśmy już pierwszą taką metodą, a jest nią konstruktor (__construct), który wywoływany jest automatycznie podczas inicjalizacji obiektu. Jest również metoda, która wykonywana jest na chwilę przed usunięciem obiektu, a jest nią destruktor (__destruct).

class A{
	public function __construct(){
		echo 'inicjalizacja';
	}

	public function __destruct(){
		echo 'destrukcja';
	}
}

Destruktor musi być publiczny i nie przyjmuje żadnych argumentów. Zastosowanie tej metody to zamknięcie otwartych zasobów (połączenia z bazą danych, uchwytu pliku) lub też zapis jakiś danych (do bazy danych lub pliku), które obiekt zbierał podczas swojego istnienia.

  • __get - próba dostępu do składowej, która nie istnieje lub jest niewidoczna dla klasy
  • __set - próba zapisania wartości do składowej, która nie istnieje lub jest niewidoczna dla klasy
  • __isset - wywołanie funkcji isset() lub empty() na składowej, która nie istnieje lub jest niewidoczna dla klasy
  • __unset - wywołanie funkcji unset() na składowej, która nie istnieje lub jest niewidoczna dla klasy
class ArrayBox{
	private $data = array();

	public function __get($name){
		return (isset($this->data[$name]) ? $this->data[$name] : null);
	}
	
	public function __set($name, $value){
		$this->data[$name] = $value;
	}

	public function __isset($name){
		return isset($this->data[$name]);
	}

	public function __unset($name){
		$this->data[$name] = null;
	}
}
$array = new ArrayBox();
$array->test = 'test';//wywołanie __set("test", "test")
echo $array->test;//wywołanie __get("test")
if(isset($array->test)){//wywołanie __isset("test")
	unset($array->test);//wywołanie __unset("test")
}
  • __call - wywołanie nieistniejącej metody
  • __callStatic - wywołanie nieistniejącej metody statycznej

Obydwie metody przyjmują jako pierwszy parametr nazwę wywołanej metody, a jako drugi tablicę argumentów.

class Dummy{
    public function __call($method, $args){
	$sArgs = (count($args) > 0 ? '"'.implode('", "', $args).'"' : '');
        echo 'Wywołano $this->'.$method.'('.$sArgs.')';
    }
/* będzie działało od php5.3 */
    public static function __callStatic($method, $args){
	$sArgs = (count($args) > 0 ? '"'.implode('", "', $args).'"' : '');
	echo 'Wywołano '.get_class($this).'::'.$method.'('.$sArgs.')';
    }
}
$dummy = new Dummy();
$dummy->test();
$dummy::test();//5.3

Istnieją jeszcze dwie dosyć istotne magiczne metody __toString oraz __clone. Pierwsza z nich jest wywoływana gdy nastąpi próba przekonwertowania obiektu na łańcuch znaków, druga z nich zaś podczas klonowania obiektu za pomocą słowa kluczowego clone. Metoda __toString powinna zwracać łańcuch znaków.

class Dog{
    private $name;
    public function __construct($name){
	$this->name = $name;
    }
    public function __toString(){
	return $this->name;
    }
}
$reksio = new Dog('Reksio');
echo $reksio;//wyświetli 'Reksio'

Obiekty w php5 są przekazywane przez referencję, co ilustruje poniższy przykład.

$oArray = class ArrayBox();//klasa z jednego z poprzednich przykładów
$oArray ->v = 'test';
$oArray2 = $oArray ;//skopiowanie referencji do obiektu, a nie samego obiektu!
$oArray2->v2 = 'test2';
echo $oArray->v2;//wyświetli 'test2', bo zmienna $v i $v2 zawierają referencję do tego samego obiektu
$oArray3 = clone $oArray;//skopiowanie obiektu I przypisanie referencji do zmiennej
$oArray3->v3 = 'test3';
echo $oArray->v3;//nic nie wyświetli gdyż $oArray3 odwołuje się do innego obiektu

Co się stanie jeśli będziemy chcieli sklonować obiekt, który będzie zawierał w jednej ze swoich składowych referencję do innego obiektu?

class Article{
	private $data = null;
	public function __construct(){
		$this->data = new ArrayBox();
	}
	public function get($name){
		return $this->data->$name;
	}
	public function set($name, $value){
		$this->data->$name = $value;
}
public function getData(){
	return $this->data;
}
}
$oArticle = new Article();
$oArticle ->set('title', 'tytuł');
$oArticle2 = clone $article;
$oArticle2->set('title', 'tytuł2');
echo $oArticle->get('title');//wyświetli “tytuł2"

Standardowe klonowanie kopiuje tylko wartości składowych obiektu, który jest klonowany. Oznacza to tyle, że obiekty które są zapisane w tych składowych nie są klonowane, a przekazywane przez referencję. Rozwiązanie problemu:

class Article{
	//ciach
	public function __clone(){
	//parametr $this w tej metodzie odnosi się do obiektu powstałego
	//na skutek klonowania, a nie obiektu klonowanego!
		$this->data = clone $this->data;
	}
	//ciach
}
Informacje na podobny temat:
Wasze opinie
Wszystkie opinie użytkowników: (3)
Błąd w przykładowym kodzie
Wtorek 16 Luty 2010 2:33:32 pm - mateo84 <mateo84_at_o2.pl>

Witam, próbowałem się zaznajomić z projektowaniem obiektowym w php i pozytywnie odbieram fakt, że komuś chce się pisać te wszystkie poradniki i tutoriale, tak jak ten. Ale niestety mam uwagę. 3. Modyfikacja dostępu w kodzie 4 (licząc od góry) metoda getName() nie wyświetla ani Reksio ani też Jamnik Reksio. Zapewne dlatego że gdzieś wypadałoby wpisać "echo". Jeżeli jest to zależne od konfiguracji serwera to przepraszam ja, ale jeżeli autor nie przetestował działania skryptu to coś tu jest nie "helloł".
Pozdrawiam :)

Za malo o istocie OOP
Niedziela 29 Marzec 2009 7:22:56 pm - seth

Brakuje mi w tym artykule opisu filozofii pisania obiektowego. To co w nim jest to tylko opis narzedzi ktore udostepnia PHP 5, a przeciez programowanie obiektowe to cos wiecej niz uzywanie slowek class, extend itp.

Jako, ze jest to tekst dla poczatkujacych brak wprowadzenia w istote OOP jest dla mnie bardzo duzym minusem.

Jezeli juz kogos chcemy uczyc obiektowki to zadbajmy o to aby wiedzial po co mu to do szczescia i jakie problemy rozwiazuje. W przeciwnym razie osoba taka dostaje do reki mlotek z instrukcja obslugi ale nie wie po co w ogole ma wbijac te gwozdzie.

Nie dla początkujących
Piątek 27 Marzec 2009 9:36:11 pm - orglee

Panie Piotrze posługuje się Pan bardzo hermetycznym językiem, opisując podstawy obiektówki. Nie wiem czy będąc początkującym zrozumiałbym więcej niż połowę z tego artykułu. Oprócz tego czasami wyprzedza Pana, Pańskie myślenie. Przykładem może być, użycie słów opisujących proces dziedziczenia, przed wytłumaczeniem istoty tego zagadnienia.

Mentax.pl    NQ.pl- serwery z dodatkiem świętego spokoju...   
O nas | Kontakt | Mapa serwisu
Copyright (c) 2003-2017 php.pl    Wszystkie prawa zastrzeżone    Powered by eZ publish Content Management System eZ publish Content Management System