2009-10-10 9 views
21

Czy brakuje mi czegoś lub naprawdę nie ma wsparcia dla ogólnego rodzaju podpowiedzi typu w PHP 5.x?Podpowiedź typu PHP: obsługiwana tablica, obiekt NIE?

Uważam, że to naprawdę dziwne, że podpowiedzi tablic są obsługiwane, gdy podpowiadanie obiektów nie jest, przynajmniej nie po wyjęciu z pudełka.

Chciałbym mieć coś takiego:

function foo(object $o) 

Podobnie jak mamy:

function foo(array $o) 

Przykład możliwego użycia: Metody klasy zbierania przedmiotów.

Obejście: za pomocą interfejsu „obiekt” realizowany przez wszystkich klasach lub przedłużenia wszystkich klas z ogólnej klasy „obiekt” i pisząc coś takiego:

function foo(Object $o) 

Dobrze, że po prostu nie jest słodkie.

Korzystanie stdClass jako wskazówkę typu nie działa:

Catchable fatal error: Argument 1 passed to c::add() must be an instance of stdClass, instance of b given

+1

Nie należy stosować typów betonu do podpowiedzi typu. Użyj interfejsów lub przeczytaj o pisaniu z kaczką. –

+0

Jeśli mam chodzić nie ścieżkami konkretnych typów wolałbym użyć is_object(). Ale nie o to chodzi w tej dyskusji. –

+5

Spójrz, PHP to bardzo niespójny język, w którym obiekty nie dziedziczą z pojedynczej klasy, tak jak w Javie. Fakt, że nie ma typowego wzmianki o obiektach ogólnych, jest rzeczywiście niedopatrzeniem, ale myślę, że musicie przejść ten punkt i przygotować się na inne dziwne rzeczy. –

Odpowiedz

6

Nie, to nie może być zrobione. Niczego nie przeoczyłem.

+0

nieprawda. Zobacz moją odpowiedź –

7

Od typu podpowiadania powinna kod klienta dostosować do API, rozwiązanie z akceptacją interfejsów wydaje tylko o prawo.

spojrzeć na to w ten sposób: yourMethod(array $input) daje yourMethod() tablicę do używania, co wiesz exactly which native functions że zastosowanie i może być używany przez yourMethod().

Jeśli określisz swoją metodę, taką jak: , będziesz również wiedzieć, które metody można zastosować do $input, ponieważ wiesz o/możesz sprawdzić, który zbiór reguł towarzyszy interfejsowi yourInterface.

W twoim przypadku akceptacja dowolnego obiektu wydaje się błędna, ponieważ nie masz możliwości sprawdzenia, które metody zastosować na wejściu. Przykład:

function foo(Object $o) { 
    return $o->thisMethodMayOrMayNotExist(); 
} 

(nie sugerując, że składnia jest poprawna)

+1

Tak nie jest w przypadku klasy kolekcji obiektów, która będzie działała jako (pseudo) kontener, który nie będzie wywoływał żadnych metod na swoich elementach potomnych, ani nie użyje żadnego z ich atrybutów/właściwości. Znajomość zmiennej to obiekt, który umożliwia korzystanie z wielu funkcji natywnych, więc nie widzę twojego punktu widzenia. –

+2

Jak korzystać z podpowiedzi typu, takich jak SplObjectStorage lub ArrayObject? – chelmertz

+0

Istnieje klasa \ stdClass dla prostych obiektów kontenerowych – Kzqai

0

Dlaczego chcesz wskazać na object, gdy zamiast tego możesz wskazać rzeczywistą nazwę klasy - byłoby to o wiele bardziej przydatne. Pamiętaj też, że nie możesz również podać podpowiedzi: int, float,, , , string lub resource.

+3

Dlaczego chcesz uderzyć w tablicę? Zapamiętaj wszystkie inne typy, których nie możesz wskazać ... Ponieważ nie ma wspólnej klasy bazowej, z której pochodzą wszystkie klasy PHP, sensowne jest wskazywanie obiektu, tak jak wskazuje na tablicę. Moja opinia, ale wątpię, czy jestem sam na tym. –

+1

Tylko dlatego, że nie można wymyślić instancji do podpowiedzi typu do ogólnego obiektu, nie oznacza to, że taka potrzeba nigdy nie istnieje. Komentarz Rikkiego jest doskonałym przykładem. Fakt, że nie możesz wpisać wskazówki dla int, float, bool, string i resource, jest moim zdaniem także niedopatrzą. Było wiele przypadków, w których wolałbym jawnie ograniczyć argument tylko do liczby całkowitej. Więc zamiast tego utknąłem przy użyciu nieistotnych wywołań "is_int". –

6

Czuję twój ból, ale nie mogę znaleźć sposobu, aby to zrobić.

Pomimo tego, co powiedziało wiele innych plakatów, sensowne wydaje się szukanie podpowiedzi typu "Obiekt"; po prostu nie rozważają scenariusza, który tego wymaga.

Próbuję wykonać trochę pracy z interfejsem API do refleksji iz tego powodu nie obchodzi mnie, jaka klasa została przekazana do mojej funkcji. Wszystko, co mnie obchodzi, to to, że jest to obiekt. Nie chcę int, float, string lub array. Chcę obiektu. Biorąc pod uwagę, że refleksja jest teraz częścią PHP, z pewnością ma sens podpowiedź typu obiektu.

2

Oto kolejny przykład, gdzie jest to wymagane ...

I utworzeniu klasy do realizacji blokowania rekordu. Rekordy będące jednym z wielu różnych typów obiektów. Klasa blokująca ma kilka metod, które wymagają obiektu (tego, który ma być zablokowany), ale nie obchodzi go, jaki to jest obiekt.

E.g.

public static function lockRecord($record, User $user, $timeout=null) 
{ 
    if(!is_object($record)) throw new \InvalidException("Argument 1 must be an object."); 

    $lock=new Lock(); 
    $lock->setRecord($record); 
    $lock->setUser($user); 
    $lock->setTimeout($timeout); 
    $lock->activate(); 
    return($lock); 
} 

Zobaczysz, że moje rozwiązanie było użyć is_object() i wyjątek, ale ja zdecydowanie wolę być w stanie zrobić to z rodzaju podpowiedzi zamiast.

Ok, więc nie koniec świata, ale myślę, że to wstyd.

4

Nie możesz po prostu powiedzieć "obiekt", gdy typ rzuca obiekt ... musisz zdefiniować KTÓRY obiekt, którego oczekujesz.

Od: http://php.net/manual/en/language.oop5.typehinting.php

class MyClass 
{ 
    /** 
    * A test function 
    * 
    * First parameter must be an object of type OtherClass 
    */ 
    public function test(OtherClass $otherclass) { 
     echo $otherclass->var; 
    } 


    /** 
    * Another test function 
    * 
    * First parameter must be an array 
    */ 
    public function test_array(array $input_array) { 
     print_r($input_array); 
    } 
} 

// Another example class 
class OtherClass { 
    public $var = 'Hello World'; 
} 
0
public static function cloneObject($source) 
{ 
    if ($source === null) 
    { 
     return null; 
    } 

    return unserialize(serialize($source)); 
} 

To gdzie będzie to potrzebne.

+4

Aby poprawić jakość odpowiedzi, dołącz/wyjaśnij, w jaki sposób/dlaczego Twój post rozwiązał problem. –

3

Najlepszym sposobem wymuszenia tego byłoby stworzenie zdegenerowanego interfejsu o nazwie Object. Zdegenerowany interfejs oznacza, że ​​nie ma zdefiniowanych metod.

interface Object { 

    // leave blank 

} 

Następnie w klasach bazowych można wdrożyć Object.

class SomeBase implements Object { 

    // your implementation 

} 

Teraz można połączyć się z funkcji, jak chciał

function myFunc (Object $obj); 

myFunc($someBase); 

Jeśli przekazać dowolny obiekt, który dziedziczy interfejsu Object tego rodzaju wskazówka minie. Jeśli przekażesz tablicę, int, string itp., Podpowiedź typu nie powiedzie się.

+0

Niestety, jest to prawdopodobnie najbliższa wersja PHP, ale oznacza to, że każda klasa, którą tworzysz, musi implementować interfejs "Object", który jest naprawdę dużo narzutów na coś tak prostego jak ten. Ahhhhh, PHP .. – mAAdhaTTah

+3

PO już opisał tę strategię w pytaniu jako możliwe obejście i jest to trochę do bani; nie pozwoli to na przekazywanie instancji wbudowanych klas lub klas zdefiniowanych w bibliotekach innych firm. –

1

Obiekty w php nie są podklasami niektórych StdClass lub Object, jak to jest w innych językach OOP. Tak więc nie ma sposobu na wpisanie przedmiotu do wiadomości. Ale widzę twoją sprawę, ponieważ czasami chcesz się upewnić, że Obiekt jest przekazywany, więc myślę, że jedynym sposobem jest podniesienie problemu ręcznie.

public function yourFunction($object){ 
    if(is_object($object)){ 
     //TODO: do something 
    }else{ 
     throw new InvalidArgumentException; 
    } 
} 

od PHP 5.4 jest również typ wskazówkę wywoływalnym. Zobacz instrukcję php: http://php.net/manual/en/language.types.callable.php