Czy istnieje sposób na zdefiniowanie abstrakcyjnych właściwości klas w PHP?
abstract class Foo_Abstract {
abstract public $tablename;
}
class Foo extends Foo_Abstract {
//Foo must 'implement' $property
public $tablename = 'users';
}
php
oop
abstract-class
Tamás Pap
źródło
źródło
Nie, nie ma sposobu, aby wymusić to za pomocą kompilatora, musiałbyś użyć sprawdzeń w czasie wykonywania (powiedzmy w konstruktorze) dla
$tablename
zmiennej, np .:Aby wymusić to dla wszystkich klas pochodnych Foo_Abstract, musiałbyś utworzyć konstruktor Foo_Abstract
final
, zapobiegając nadpisywaniu.Zamiast tego możesz zadeklarować abstrakcyjny getter:
źródło
W zależności od kontekstu właściwości, jeśli chcę wymusić deklarację abstrakcyjnej właściwości obiektu w obiekcie podrzędnym, lubię używać stałej ze
static
słowem kluczowym dla właściwości w konstruktorze obiektów abstrakcyjnych lub metodach ustawiających / pobierających. Opcjonalnie można użyć,final
aby zapobiec przesłonięciu metody w klasach rozszerzonych.Poza tym obiekt potomny przesłania właściwość i metody obiektu nadrzędnego, jeśli zostanie ponownie zdefiniowany. Na przykład, jeśli właściwość jest zadeklarowana jako
protected
nadrzędna i przedefiniowana tak, jakpublic
w przypadku elementu podrzędnego, wynikowa właściwość jest publiczna. Jeśli jednak nieruchomość zostanie zadeklarowanaprivate
w rodzicu, pozostanieprivate
i nie będzie dostępna dla dziecka.http://www.php.net//manual/en/language.oop5.static.php
źródło
Jak stwierdzono powyżej, nie ma takiej dokładnej definicji. Ja jednak używam tego prostego obejścia, aby zmusić klasę podrzędną do zdefiniowania właściwości „abstract”:
źródło
static
nieruchomości.the only "safe" methods to have in a constructor are private and/or final ones
, czy moje obejście nie jest w takim przypadku? używam w tym szeregowych$name
. Możesz zaimplementować tęsetName()
funkcję bez jej faktycznego ustawienia$name
.getName
zamiast$name
działa lepiej.abstract class Father { abstract protected function getName(); public function foo(){ echo $this->getName();} }
Zadałem sobie dzisiaj to samo pytanie i chciałbym dodać moje dwa centy.
Powodem, dla którego chcielibyśmy
abstract
właściwości jest upewnienie się, że podklasy je definiują i zgłaszanie wyjątków, gdy tego nie robią. W moim przypadku potrzebowałem czegoś, co mogłoby współpracować zstatic
sojusznikiem.Idealnie chciałbym coś takiego:
Skończyło się na tej implementacji
Jak widać,
A
nie definiuję$prop
, ale używam go wstatic
getterze. Dlatego działa następujący kodW
C
natomiast nie definiuję$prop
, więc dostaję wyjątki:Muszę wywołać
getProp()
metodę, aby uzyskać wyjątek i nie mogę jej uzyskać podczas ładowania klasy, ale jest dość blisko pożądanego zachowania, przynajmniej w moim przypadku.I zdefiniować
getProp()
jakofinal
celu uniknięcia że niektóre mądry facet (aka siebie w ciągu 6 miesięcy) chciałoby się zrobićźródło
Jak mogłeś się dowiedzieć, po prostu testując swój kod:
Nie, nie ma. Właściwości nie mogą być deklarowane jako abstrakcyjne w PHP.
Możesz jednak zaimplementować abstrakcyjną funkcję pobierającą / ustawiającą, może to być to, czego szukasz.
Właściwości nie są zaimplementowane (zwłaszcza właściwości publiczne), po prostu istnieją (lub nie):
źródło
Potrzeba abstrakcyjnych właściwości może wskazywać na problemy projektowe. Chociaż wiele odpowiedzi implementuje wzorzec metody Template i działa, zawsze wygląda to trochę dziwnie.
Spójrzmy na oryginalny przykład:
Zaznaczenie czegoś
abstract
oznacza wskazanie, że jest to rzecz obowiązkowa. Cóż, wartość obowiązkowa (w tym przypadku) jest wymaganą zależnością, więc powinna zostać przekazana do konstruktora podczas tworzenia instancji :Następnie, jeśli faktycznie chcesz bardziej konkretnej nazwanej klasy, możesz dziedziczyć w następujący sposób:
Może to być przydatne, jeśli używasz kontenera DI i musisz przekazywać różne tabele dla różnych obiektów.
źródło
PHP 7 znacznie ułatwia tworzenie abstrakcyjnych "właściwości". Tak jak powyżej, stworzysz je, tworząc abstrakcyjne funkcje, ale w PHP 7 możesz zdefiniować typ zwracania dla tej funkcji, co znacznie ułatwia budowanie klasy bazowej, którą każdy może rozszerzyć.
źródło
jeśli wartość tablename nigdy się nie zmieni w czasie życia obiektu, następująca będzie prosta, ale bezpieczna implementacja.
kluczem jest tutaj to, że wartość ciągu „users” jest określona i zwrócona bezpośrednio w funkcji getTablename () w implementacji klasy potomnej. Funkcja naśladuje właściwość „tylko do odczytu”.
Jest to dość podobne do rozwiązania opublikowanego wcześniej, w którym używana jest dodatkowa zmienna. Podoba mi się również rozwiązanie Marco, chociaż może być nieco bardziej skomplikowane.
źródło