Czym różni się przekazywanie parametru przez wartość a przez zmienną? Wielu początkujących programistów nie wie, jak to dobrze wykorzystać. Jeśli masz podobny problem, przeczytaj ten artykuł.
Wielu początkujących programistów nie widzi różnicy pomiędzy przekazywaniem parametru przez wartość a przekazywaniem parametru przez zmienną zwanym referencją. Otóż różnica jest, dzięki tym dwóm metodom można znacznie efektywniej pracować z funkcjami i nie tylko.
Krótkie przypomnienie:
Przekazanie przez wartość powoduje kopiowanie przekazywanej wartości do innej zmiennej, przez co powstają dwie kopie tej samej wartości. Natomiast przekazanie przez zmienną (czyli wstawiając przed deklaracją zmiennej znak „&” np. &$jakas_zmienna) powoduje utworzenie zmiennej z odwołaniem do przekazywanej wartości (wskaźnik do miejsca w pamięci). Gdy przekazujemy przez wartość, zmiana wartości jednej z kopii nie powoduje zmiany w drugiej, natomiast, gdy przekażemy przez zmienną zmiana w jednej powoduje zmianę w drugiej. Nic bardziej błędnego niż uważać, że nie ma to różnicy. Zrozumienie tej właśnie różnicy może zaoszczędzić bałaganu w kodzie programu.
Jak to wygląda w praktyce.
Dla przykładu tworzymy funkcję i dwie zmienne z ustawiając im inne wartości:
$zmiennaA = 5; $zmiennaB = 10; function funkcja( $zmienna ) |
Następnie wywołujemy tą funkcję dla dwóch zmiennych.
funkcja( $zmiennaA ); funkcja( &$zmiennaB ); |
Teraz możemy wyświetl wartość obu zmiennych:
echo $zmiennaA; |
Da w wyniku:
5 |
Druga zmienna:
echo $zmiennaB; |
Da w wyniku:
30 |
Dlaczego tak się dzieje? Zmienna $zmiennaA została przekazana przez wartość i została utworzona kopia tej zmiennej w ciele funkcji, w której zmiany nie dotyczą zmiennej przekazanej jako parametr. Zmienna $zmiennaB natomiast zmieniła swoją wartość, dlatego bo zamiast tworzyć kopię tej wartości zostało utworzone odwołanie do miejsca w pamięci przechowującego tą zmienną.
Ktoś może powiedzieć, że można to zrobić inaczej np.:
$zmiennaA = funkcja( $zmiennaA ); |
W porządku da się tak, ale to jest głupie pytanie, równie dobrze można zapytać, po co jest inkrementacja, bo przecież, po co robić tak:
$zmienna++; |
skoro można zrobić tak:
$zmienna += 1; |
albo nawet:
$zmienna = $zmienna + 1; |
jak ktoś uważa, że takie działanie jest uzasadnione to proszę bardzo.
Kiedy użyć przekazania przez wartość a kiedy przez zmienną:
Odpowiedź jest prosta, przekazujemy przez zmienną, kiedy chcemy zmodyfikować daną zmienną w jakiś sposób, a przez wartość wtedy, gdy potrzebujemy oddzielnej zmodyfikowanej wartości danej zmiennej.
W praktyce prezentuje to się tak.
Wezmę przykład wszystkim znany, mam tablicę z imionami:
$imiona = array( „Tomek”, „Romek”, „Atomek”, „Tomek”, „Bolek”, „Lolek” ); |
teraz chcę ją posortować, więc używam funkcji sort(), ale w ten sposób:
sort( $imiona ); |
jasne jest chyba, dlaczego w tej formie, bo po co mi oddzielna kopia tablicy z posortowanymi i nie posortowanymi imionami. Mam w wyniku posortowaną tablice z imionami. Ale teraz chcę, wypisać jakie imiona mam w tablicy, tzn. bez powtarzających się, wykorzystam do tego funkcję array_unique():
$spis_imion = array_unique( $imiona ); |
tym razem potrzebuję oddzielnej tablicy, gdyż wykonanie zmian na głównej tablicy spowodowałoby nieodwracalne zmiany i utratę części danych, a tak mam dwie tablice, które będą potrzebne w różnych momentach.
!!!Uwaga ktoś by zapytał, dlaczego napisałem sort($imiona) a nie sort(&$imiona), owszem można napisać tak i tak tylko, że nie robi to różnicy gdyż funkcja sort() nie zwraca wyniku i zmiany zapisuje automatycznie do parametru. Jest to działanie intuicyjne, bo z założenia, po co komu ta sama tablica posortowana i nie posortowana??? Jeśli ktoś już takiej potrzebuje to może napisać tak:
$imiona_NP = $imiona; sort($imiona); |
wówczas zachowa nie posortowaną wersję. Natomiast funkcja array_unique() dokonuje znaczących zmian w parametrze i nierozsądnym byłoby gdyby zapisywała zmiany bezpośrednio do parametru, ale oczywiście jest to możliwe poprzez przekazanie przez zmienną:
array_unique(&$imiona); |
To tyle, jeżeli chodzi o przekazywanie wartości przez wartość i przez zmienną.
Przekazywanie przez zmienną jest również możliwe w klasach i obiektach, mamy na przykład klasę Mors z dwiema metodami: zaszyfruj i odszyfruj, definicja wygląda następująco:
class Mors { function zaszyfroj( $ciag ) |
teraz trzeba stworzyć egzemplarz klasy Mors:
$alfabet_morsa = new Mors; |
a następnie wykorzystać jego metodę:
$zaszyfrowany_ciąg = $alfabet_morsa->zaszyfruj( $ciag_do_zaszyfrowania ); |
to jest jeden ze sposobów wykorzystujący przekazanie przez wartość, natomiast przekazanie przez zmienną wyglądałoby następująco:
Zmiany w Klasie:
class Mors { function zaszyfruj( $ciag ) |
teraz trzeba stworzyć egzemplarz klasy Mors:
$alfabet_morsa = new Mors; |
a następnie wykorzystać jego metodę, która może wyglądać tak:
$alfabet_morsa->zaszyfruj( &$ciag ); |
funkcja wykona się na wartości przekazanego parametru.
Jest jeszcze jedna ważna rzecz, jeśli chodzi o przekazywanie przez zmienna w klasach, a mianowicie, jeżeli zmienna ma być przechowywana w klasie deklaracja przekazania przez zmienną musi być również w definicji klasy, np.:
class Magazyn { var $cenaWMagazynie; function zapiszcene( $cena ) |
Teraz tworzymy egzemplarz klasy magazyn:
$mojMagazyn = new Magazyn; |
przekazuję cenę do obiektu $mojMagazyn:
$cenaZaMagazynem = „50 zł”; $mojMagazyn->zapiszcene( $cenaZaMagazynem ); |
w ten sposób mamy zmienną i właściwość ustawiona na wartość „50 zł”. Wartość została przekazana przez zmienną, zmiana wartości którejkolwiek ze zmiennych powoduje automatyczną zmianę w drugiej.
!!!Uwaga, należy pamiętać, aby przekazanie przez zmienną „&” zastosować przy przekazywaniu wartości do obiektu i w obiekcie, tak jak to pokazano na przykładzie.