2014-11-17 10 views
7

W podpowiedzi typu php-s nie mogę używać typów skalarnych, takich jak liczba całkowita lub łańcuch. Tak więc jest to nieważne:Używaj klas otoki, jak w JAVA, gdy typ podpowiedzi

function myFunc(int $num) { 
    //... 
} 

Czy można używać klas otoki, jak w JAVA? Integer, String, Boolean, itp ...

chciałbym używać go tak:

function myFunc(Integer $num) { 
    //... 
} 

myFunc(5);  // ok 
myFunc("foo"); // error 

wiem, nie ma żadnych klasy otoki w PHP domyślnie. Ale jak to możliwe, aby napisać?

+0

Można jako przykład wewnątrz testu użyć funkcji is_integer lub is_numeric lub is_string, etc ... –

+0

Tak, jest to możliwe, istnieją rozwiązania dla tego użytkownika w przyczyniła rozdział instrukcji : http://php.net/manual/en/language.oop5.typehinting.php Ale wątpię, czy to dobry pomysł. Będzie to mylące dla innych programistów i prawdopodobnie powolne. Jeśli chcesz statycznie napisany język, użyj jednego (jak java lub facebook Hack). – Steve

Odpowiedz

5

Ponieważ PHP 5 PHP pozwala type hinting pomocą klas (zmuszających parametr funkcja/metoda może być wystąpienie classs).

Można więc utworzyć klasę int, która pobiera liczbę całkowitą PHP w konstruktorze (lub analizuje liczbę całkowitą, jeśli pozwala się na łańcuch zawierający liczbę całkowitą, jak na przykład w poniższym przykładzie) i oczekuje tego w parametrze funkcji.

int klasa

<?php 

class int 
{ 

    protected $value; 

    public function __construct($value) 
    { 
     if (!preg_match("/^(0|[-]?[1-9][0-9])*$/", "$value")) 
     { 
     throw new \Exception("{$value} is not a valid integer."); 
     } 
     $this->value = $value; 
    } 

    public function __toString() 
    { 
     return '' . $this->value; 
    } 

} 

Demo

$test = new int(42); 
myFunc($test); 

function myFunc(int $a) { 
    echo "The number is: $a\n"; 
} 

Wynik

KolyMac:test ninsuo$ php types.php 
The number is: 42 
KolyMac:test ninsuo$ 

Ale powinieneś uważać na efekty uboczne.

instancję int oceni do true jeśli używasz go w środku wyrazu (takich jak, $test + 1), zamiast 42 w naszym przypadku. Należy użyć wyrażenia "$test" + 1, aby uzyskać 43, ponieważ __toString jest wywoływane tylko podczas próby rzutowania obiektu na ciąg znaków.

Uwaga: nie trzeba zawijać typ array, jak można natywnie wpisać-podpowiedź go na parametry funkcji/metody.

float klasy

<?php 

class float 
{ 

    protected $value; 

    public function __construct($value) 
    { 
     if (!preg_match("/^(0|[-]?[1-9][0-9]*[\.]?[0-9]*)$/", "$value")) 
     { 
     throw new \Exception("{$value} is not a valid floating number."); 
     } 
     $this->value = $value; 
    } 

    public function __toString() 
    { 
     return $this->value; 
    } 

} 

Klasa string

<?php 

class string 
{ 

    protected $value; 

    public function __construct($value) 
    { 
     if (is_array($value) || is_resource($value) || (is_object($value) && (!method_exists($value, '__toString')))) 
     { 
     throw new \Exception("{$value} is not a valid string or can't be converted to string."); 
     } 
     $this->value = $value; 
    } 

    public function __toString() 
    { 
     return $this->value; 
    } 

} 

bool klasy

class bool 
{ 

    protected $value; 

    public function __construct($value) 
    { 
     if (!strcasecmp('true', $value) && !strcasecmp('false', $value) 
      && !in_array($value, array(0, 1, false, true))) 
     { 
     throw new \Exception("{$value} is not a valid boolean."); 
     } 
     $this->value = $value; 
    } 

    public function __toString() 
    { 
     return $this->value; 
    } 

} 

object klasa

class object 
{ 

    protected $value; 

    public function __construct($value) 
    { 
     if (!is_object($value)) 
     { 
     throw new \Exception("{$value} is not a valid object."); 
     } 
     $this->value = $value; 
    } 

    public function __toString() 
    { 
     return $this->value; // your object itself should implement __tostring` 
    } 

} 
+0

Czy muszę utworzyć wszystkie int z nowym słowem kluczowym? Czy nie jest możliwe, aby jakoś zrealizować autoboxing/unboxing? –

+0

Nie, PHP tego nie obsługuje :( –

+1

Nie, to niemożliwe ... Używając tego rodzaju klas, to jest jak w C, powinieneś zadeklarować swoje zmienne przed ich użyciem (np. $ Var = new int (42); '), to nie jest całkiem naturalne w php :-). –

1

Brak klas owijki dla wartości pierwotnych, nie. Domyślam się, że możesz ręcznie sprawdzić typ:

function myFunc($num) { 
    if(!is_int($num)) { 
     throw new Exception('First parameter must be a number'); 
    } 
    // ... 
} 

To nie byłby jednak prawdziwy typ podpowiedzi.

Najlepszym sposobem byłoby prawdopodobnie udokumentowanie twojego kodu i mając nadzieję, że jest on używany poprawnie.

/** 
* @param int $num 
*/ 
function myFunc($num) { 
    // ... 
}