Po włączeniu ścisłych ostrzeżeń w PHP 5.2, zobaczyłem ładunek ostrzeżeń o ścisłych standardach z projektu, który został pierwotnie napisany bez ścisłych ostrzeżeń:
Ścisłe standardy : funkcja statyczna Program :: getSelectSQL () nie powinna być abstrakcyjna w Program.class.inc
Omawiana funkcja należy do abstrakcyjnej klasy nadrzędnej Program i jest deklarowana jako abstrakcyjna statyczna, ponieważ powinna być zaimplementowana w jej klasach potomnych, takich jak TVProgram.
Znalazłem odniesienia do tej zmiany tutaj :
Usunięto abstrakcyjne funkcje klas statycznych. Z powodu przeoczenia PHP 5.0.x i 5.1.x dopuszcza abstrakcyjne funkcje statyczne w klasach. Od PHP 5.2.x mogą je mieć tylko interfejsy.
Moje pytanie brzmi: czy ktoś może wyjaśnić w jasny sposób, dlaczego w PHP nie powinno być abstrakcyjnej funkcji statycznej?
Odpowiedzi:
metody statyczne należą do klasy, która je zadeklarowała. Rozszerzając klasę, możesz stworzyć statyczną metodę o tej samej nazwie, ale tak naprawdę nie implementujesz statycznej metody abstrakcyjnej.
To samo dotyczy rozszerzania dowolnej klasy metodami statycznymi. Jeśli rozszerzysz tę klasę i utworzysz metodę statyczną o tej samej sygnaturze, w rzeczywistości nie zastąpisz statycznej metody nadklasy
EDYCJA (16 września 2009)
Aktualizacja na ten temat. Uruchamiam PHP 5.3 i widzę, że abstrakcyjna statystyka powróciła, na dobre lub na złe. (zobacz http://php.net/lsb, aby uzyskać więcej informacji)
KOREKCJA (autorstwa philfreo)
abstract static
nadal nie jest dozwolona w PHP 5.3, LSB jest powiązane, ale inne.źródło
abstract static
może być przydatne w tym przypadku.To długa, smutna historia.
Kiedy PHP 5.2 po raz pierwszy wprowadziło to ostrzeżenie, późne statyczne wiązania nie były jeszcze w języku. Jeśli nie jesteś zaznajomiony z późnymi wiązaniami statycznymi, zwróć uwagę, że taki kod nie działa tak, jak można się spodziewać:
Pomijając ostrzeżenie o trybie ścisłym, powyższy kod nie działa.
self::bar()
Rozmowyfoo()
wyraźnie odnosi się dobar()
metodyParentClass
, nawet jeślifoo()
jest nazywany jako metodyChildClass
. Jeśli spróbujesz uruchomić ten kod przy wyłączonym trybie ścisłym, zobaczysz komunikat „ Błąd krytyczny PHP: nie można wywołać metody abstrakcyjnej ParentClass :: bar () ”.Biorąc to pod uwagę, abstrakcyjne metody statyczne w PHP 5.2 były bezużyteczne. Cały punkt z zastosowaniem metody abstrakcyjne, że można napisać kod, który wywołuje metodę, nie wiedząc, co to realizacja będzie powołanie - a następnie dostarczyć różne implementacje na różnych klasach potomnych. Ale ponieważ PHP 5.2 nie oferuje prostego sposobu na napisanie metody klasy nadrzędnej, która wywołuje statyczną metodę klasy potomnej, na której jest wywoływana, takie użycie abstrakcyjnych metod statycznych nie jest możliwe. Stąd jakiekolwiek użycie
abstract static
w PHP 5.2 jest złym kodem, prawdopodobnie zainspirowanym niezrozumieniem działaniaself
słowa kluczowego. Było całkowicie rozsądne, aby ostrzec w tej sprawie.Ale potem pojawił się PHP 5.3 z możliwością odwoływania się do klasy, dla której metoda została wywołana za pomocą
static
słowa kluczowego (w przeciwieństwie doself
słowa kluczowego, które zawsze odnosi się do klasy, w której metoda została zdefiniowana ). Jeśli zmieniszself::bar()
nastatic::bar()
w moim przykładzie powyżej, działa dobrze w PHP 5.3 i nowszych. Możesz przeczytać więcej oself
vsstatic
at Nowa jaźń kontra nowa statystyka .Po dodaniu słowa kluczowego static wyraźny argument za
abstract static
wysłaniem ostrzeżenia zniknął. Głównym celem późnych wiązań statycznych było umożliwienie metodom zdefiniowanym w klasie nadrzędnej wywoływanie metod statycznych, które zostałyby zdefiniowane w klasach potomnych; dopuszczenie abstrakcyjnych metod statycznych wydaje się rozsądne i spójne, biorąc pod uwagę istnienie późnych wiązań statycznych.Wydaje mi się, że nadal możesz argumentować za utrzymaniem ostrzeżenia. Na przykład, można argumentować, że skoro PHP umożliwia wywoływanie metod statycznych klas abstrakcyjnych, w moim przykładzie powyżej (nawet po zamontowaniu go zastępując
self
zstatic
) jesteś narażając sposób publicznyParentClass::foo()
, który jest uszkodzony i że tak naprawdę nie chcą expose. Użycie klasy niestatycznej - to znaczy uczynienie wszystkich metod instancjami metodami i uczynienie ich elementów potomnychParentClass
jako singletonów lub coś w tym rodzaju - rozwiązałoby ten problem, ponieważParentClass
będąc abstrakcyjnymi, nie można utworzyć instancji, więc metody instancji nie mogą Zostać wezwanym. Myślę, że ten argument jest słaby (ponieważ myślę, że ujawniamParentClass::foo()
to nic wielkiego i używanie singletonów zamiast klas statycznych jest często niepotrzebnie rozwlekłe i brzydkie), ale możesz się z tym nie zgodzić - jest to nieco subiektywne wezwanie.Bazując na tym argumencie, twórcy PHP zachowali ostrzeżenie w języku, prawda?
Uh, nie dokładnie .
Raport o błędzie PHP 53081, do którego łącze powyżej, wezwał do usunięcia ostrzeżenia, ponieważ dodanie
static::foo()
konstrukcji sprawiło, że abstrakcyjne metody statyczne stały się rozsądne i użyteczne. Rasmus Lerdorf (twórca PHP) zaczyna od oznaczenia żądania jako fałszywego i przechodzi przez długi łańcuch złych argumentów, próbując uzasadnić ostrzeżenie. W końcu dochodzi do wymiany:Twierdzenie Rasmusa, że kod w jego przykładzie „działa dobrze” jest fałszywe; jak wiesz, generuje ostrzeżenie o trybie ścisłym. Wydaje mi się, że testował bez włączonego trybu ścisłego. Mimo wszystko zdezorientowany Rasmus pozostawił prośbę błędnie zamkniętą jako „fałszywą”.
I dlatego ostrzeżenie jest nadal w języku. Może to nie być w pełni satysfakcjonujące wyjaśnienie - prawdopodobnie przyszedłeś tutaj z nadzieją, że ostrzeżenie zostało racjonalnie uzasadnione. Niestety, w prawdziwym świecie czasami wybory rodzą się z przyziemnych błędów i złego rozumowania, a nie z racjonalnego podejmowania decyzji. To po prostu jeden z tych czasów.
Na szczęście szacowny Nikita Popov usunął ostrzeżenie z języka w PHP 7 jako część notatek PHP RFC: Reclassify E_STRICT . Ostatecznie zwyciężył rozsądek i po wydaniu PHP 7 wszyscy możemy z radością korzystać
abstract static
bez otrzymywania tego głupiego ostrzeżenia.źródło
Istnieje bardzo proste obejście tego problemu, które w rzeczywistości ma sens z punktu widzenia projektowania. Jak napisał Jonathan:
Więc jako obejście możesz to zrobić:
A teraz wymuszasz, aby każda klasa podrzędna MyFoo implementowała statyczną metodę getInstance i publiczną metodę getSomeData. A jeśli nie utworzysz podklasy MyFoo, nadal możesz zaimplementować iMyFoo, aby utworzyć klasę o podobnej funkcjonalności.
źródło
static::
może się przydać.abstract static
metody, bez narzekania na PHP…Wiem, że to jest stare, ale ....
Dlaczego po prostu nie rzucić wyjątku do statycznej metody tej klasy nadrzędnej, w ten sposób, jeśli jej nie zastąpisz, wyjątek zostanie spowodowany.
źródło
Twierdziłbym, że abstrakcyjna klasa / interfejs może być postrzegana jako kontrakt między programistami. Zajmuje się bardziej tym, jak rzeczy powinny wyglądać / zachowywać się, a nie implementować rzeczywistej funkcjonalności. Jak widać w php5.0 i 5.1.x, nie jest to naturalne prawo, które uniemożliwia programistom php zrobienie tego, ale chęć współdziałania z innymi wzorcami projektowymi OO w innych językach. Zasadniczo te pomysły mają na celu zapobieżenie nieoczekiwanym zachowaniom, jeśli ktoś jest już zaznajomiony z innymi językami.
źródło
Nie widzę powodu, aby zabraniać statycznych funkcji abstrakcyjnych. Najlepszym argumentem, że nie ma powodu, aby ich zabraniać, jest to, że są one dozwolone w Javie. Oto pytania: - Czy jest to technicznie wykonalne? - Tak, ponieważ istniały w PHP 5.2 i istnieją w Javie. Więc gdzie MOŻE to zrobić. POWINNIŚMY to zrobić? - Czy mają sens? Tak. Warto zaimplementować część klasy i pozostawić inną część klasy użytkownikowi. Ma to sens w funkcjach niestatycznych, dlaczego nie miałoby mieć sensu w przypadku funkcji statycznych? Jednym z zastosowań funkcji statycznych są klasy, w których nie może być więcej niż jedna instancja (pojedyncze). Na przykład silnik szyfrujący. Nie musi istnieć w kilku przypadkach i są powody, aby temu zapobiec - na przykład przed intruzami trzeba chronić tylko jedną część pamięci. Dlatego sensowne jest zaimplementowanie jednej części silnika i pozostawienie algorytmu szyfrowania użytkownikowi. To tylko jeden przykład. Jeśli jesteś przyzwyczajony do korzystania z funkcji statycznych, znajdziesz o wiele więcej.
źródło
W php 5.4+ cecha użycia:
aw swojej klasie umieść na początku:
źródło
abstract public static function get_table_name();
cechę i użyć tej cechy w mojej abstrakcyjnej klasie bez ostrzeżeń E_STRICT! To wciąż wymuszało zdefiniowanie metody statycznej u dzieci, tak jak się spodziewałem. Fantastyczny!Zajrzyj do problemów PHP z późnym wiązaniem statycznym. Jeśli umieszczasz metody statyczne w klasach abstrakcyjnych, prawdopodobnie napotkasz to wcześniej niż później. To ma sens, że surowe ostrzeżenia mówią ci, abyś unikał używania funkcji zepsutego języka.
źródło