Specificarea tipului de date al argumentelor functiilor

Post Title
function addTwoIntegers($value1, $value2) {
    return $value1 + $value2;
}

echo addTwoIntegers(1, 2); // 3

Pana aici, nimic nu pare nou, dupa cum putem observa, am creat functia addTwoIntegers() functie ce are doua argumente, reprezentand valorile ce vor fi adunate, returnand rezultatul.

Sa presupunem ca aceasta functie accepta doar valori ce au tipul de date integer, ceea ce inseamna, ca in interiorul functiei trebuie sa facem niste modificari pentru a fi siguri ca parametrii introdusi au tipul de date acceptat, astfel, avem:

function addTwoIntegers($value1, $value2) {
    if (!is_int($vakue1) || !is_int($value2)) {
        die('Functia addTwoIntegers() accepta doar valori de tip integers');
    }

    return $value1 + $value2;
}

echo addTwoIntegers(1, "sdsd"); // se executa acel die

Observam ca in interiorul functiei addTwoIntegers() facem aceste verificari, ceea ce inseamna ceva cod in plus, insa, PHP 7 a introdus posibilitatea de a specifica tipul de date acceptat de fiecare argument al unei functii, astfel putem face:

function addTwoIntegers(int $value1, int $value2) {
    return $value1 + $value2;
}

echo addTwoIntegers(1, 2); 

Interesant, folosind aceasta noua sintaxa, am scapat de acel bloc de cod necesar verificarii tipului de date.Dupa cum putem observa, am adaugat acel int, reprezentand tipul de date integer, in fata argumentelor.Acest lucru face ca acele argumente sa poata avea doar valori ce au tipul de date integer sau numere intregi.

Evident, putem specifica si celelalte tipuri de date scalare ( integer, string, bool, float ).

function sayName(string $name) {
    return $name;
}

echo sayName('Catalin'); // Catalin
function isOnline(bool $online) {
    return $online;
}

isOnline(true);
function addTwoFloats(float $value1, float $value2) {
    return $value1 + $value2;
}

echo addTwoFloats(15.7, 13.4); // 29.1

Trebuie sa retinam ca PHP poate converti tipul de date al unui parametru, pentru a satisface tipul de date al argumentului functiei.Astfel, daca un argument are nevoie de o valoare ce are tipul de date string iar noi vom introduce un integer pentru acel argument, valoarea va fi convertita ( daca se poate ) in string, astfel avem:

function getFullName(string $fullName) {
    return $fullName;
}

echo getFullName(13232); // 13232

PHP va converti integer in string si orice alt tip de date scalar in bool.De asemenea, va incerca sa converteasca string in integer daca valoarea string incepe cu o cifra.

Cum putem evita astfel de situatii?

Ei bine, putem folosi modul strict prin adaugarea directivei declare(strict_types=1); pe primul rand dupa tag-ul PHP de deschidere.

<?php
declare(strict_types=1);

function getFullName(string $fullName) {
    return $fullName;
}

echo getFullName(13232); // o eroare fatal va fi emisa

PHP 5 ofera de asemenea posibilitatea de a specifica tipul de date al argumentelor pentru array si object

Putem merge chiar mai departe, astfel, putem folosi si tipuri de date array si object ( din PHP 5 in sus )

function addTasks(array $tasks) {
    //...
}

In ceea ce priveste tipul de date object, trebuie sa folosim o alta abordare:

class User 
{
    protected $name;

    public function setName(string $name)
    {
        $this->name = $name;
    }

    public function getName()
    {
        return $this->name;
    }
}

class Mail
{
    protected $message;

    protected $user;

    public function __construct(User $user)
    {
        $this->user = $user;
    }

    public function setMessage(string $message)
    {
        $this->message = $message;
    }

    public function send()
    {
        //...
    }
}

$user = new User;
$mail = new Mail($user);

$mail->setMessage('Hello from Catalin');

$mail->send();

Am creat un exemplu foarte simplu.Dupa cum putem observa, in functia constructor a clasei Mail, am speficicat ca argumentul $user accepta doar instante ( obiecte ), ce sunt de tipul User, ale clasei User.

public function __construct(User $user)
{
    $this->user = $user;
}

Ce se intampla daca se introduce o valoare ce are un tip de date diferit de cel specificat in semnatura functiei/metodei?

function getNumber(int $number) {
    return $number;
}

echo getNumber("Cata");

Ei bine, PHP 7 va emite o eroare fatala, specificand mai multe detalii despre aceasta eroare, Fatal error: Uncaught TypeError: Argument 1 passed to getNumber() must be of the type integer, string given

Ce beneficii avem daca specificam tipul de date al argumentelor unei functii/metode?

Ei bine, se intelege de la sine, evitam scrierea unei portiuni de cod pentru a verifica daca parametrii au tipul de date necesar.Mai mult decat atat, codul scris devine mai sigur, astfel evitand tot felul de erori cauzate de introducerea unor alte valori decat cele necesare functionarii functiei/metodei.

Alte beneficii aduse

Ei bine, atunci cand vorbim de OOP, putem specifica chiar si interfete sau clase abstracte ca tip de date necesar argumentelor metodelor, astfel putem avea:

interface SocialAdapter
{
    public function postStatus(string $status);
}

class TwitterAdaptar implements SocialAdapter
{
    protected $twitter;

    public function __construct(Twitter $twitter)
    {
        $this->twitter = $twitter;
    }

    public function postStatus(string $status)
    {
        $this->twitter->sendStatusMessage($status);
    }
}

class UserController
{
    protected $socialStream;

    public function __construct(SocialAdapter $socialStream)
    {
        $this->socialStream = $socialStream;
    }

    public function sendSocialMessage(string $message)
    {
        $this->socialStream->postStatus($message);
    }
}

// aceasta clasa face partea din libraria oferita de twitter
$twitter = new Twitter();

$twitterAdaptaer = new TwitterAdapter($twitter);

$userController = new UserController($twitterAdapter);

$userController->sendSocialMessage("Helloooo");

Dupa cum putem observa, in functia constructor a clasei UserController am specificat ca tipul de date al argumentului $socialStream sa fie SocialAdapter ce este chiar interfata creata de noi.Astfel, acel argument accepta valori ce sunt instante ale claselor ce implementeaza interfata SocialAdapter.Folosind aceasta tehnica, codul devine mult mai flexibil, putem schimba clasa TwitterAdapter cu o alta clasa, sa zicem FacebookAdapter, implementand aceeasi interfata, SocialAdapter, clasa UserController tot va functiona, ea asteapta o instanta a unei clase ce implementeaza interfata SocialAdapter.Apropo, mai sus am folosit modelul de design adaptor, probabil o sa vorbim mai pe larg despre el intr-un alt articol.

Putem specifica tipul de date al valorii returnate de o functie/metoda?

Da, putem face si acest lucru, PHP 7 ne ofera posibilitatea de a specifica si ce tip de date o functie/metoda poate returna.

function getNumber(int $value) : int {
    return $value;
}

echo getNumber(10); // 10

Prin adaugarea : int dupa semnatura functiei, am specificat ca aceasta functie va returna valori ce au tipul de date integer, foarte simplu si clar. Pentru celelalte tipuri de date scalare putem folosi aceeasi sintaxa.

Daca functia/metoda returneaza o valoare ce are un tip de date diferit de cel specificat, o eroare fatala va fi emisa, spre exemplu:

function getNumber(int $value) : int {
    return "Your number is {$value}";
}

echo getNumber(10);

FATAL ERROR Uncaught TypeError: Return value of getNumber() must be of the type integer, string returned

Trebuie sa retinam ca si atunci cand specificam tipul de date pe care o functie il poate returna, PHP va incerca sa converteaca valoarea returnata ( daca nu are tipul de date necesar ) pentru a respecta tipul de date ales.

Ei bine, cam atat cu acest tutorial, sfatul meu este sa folositi PHP 7 si noile functionalitati aduse, codul scris va fi mult imbunatatit si mult mai clar.

Autor articol
David: Why do you want to leave me? Why? I'm sorry I'm not real! If you let me, I'll be so real for you!

Comentarii

Comentariu adaugat de Catalin
Mersi, am corectat niste mici greseli, sper sa fie de folos!
go to page top Catalin | 2017-03-04
Comentariu adaugat de marian
Bravo Catalin, l-am distribuit si pe pagina noastra de facebook! 
go to page top marian | 2017-03-04

Exista 2 comentarii   

  • 1
Trebuie sa fii logat sa poti lasa un comentariu Autentificare Inregistrare Logare cu Facebook
top