TL; DR: Sie können definieren abstract static
auf trait
s, aber Interna hält es schlechte Praxis und es in Zukunft entfernen.
Ich hatte nicht viel Koffein, aber ich werde einen Riss geben.
Ausschließlich abstract
bedeutet, dass die Unterklasse implementiert werden muss, und static
bedeutet nur Code für diese spezifische Klasse. Zusammengenommen bedeutet abstract static
"Unterklasse muss Code nur für diese spezifische Klasse implementieren". Total orthogonale Konzepte.
Aber ... PHP 5.3+ unterstützt statische Vererbung dank LSB. Also öffnen wir diese Definition tatsächlich ein wenig: self
nimmt die frühere Definition von statisch, während static
wird "Code für diese bestimmte Klasse oder einer seiner Unterklassen". Die neue Definition von abstract static
lautet "Unterklasse muss Code für diese bestimmte Klasse oder eine ihrer Unterklassen implementieren". Dies kann dazu führen, dass einige Leute, die an static
im engeren Sinne denken, zu Verwirrung führen. Siehe zum Beispiel bug #53081.
Was macht trait
so besonders, diese Warnung auszulösen? Nun, werfen Sie einen Blick auf die engine code, die die Bekanntmachung implementiert:
if (ptr->flags & ZEND_ACC_STATIC && (!scope || !(scope->ce_flags & ZEND_ACC_INTERFACE))) {
zend_error(error_type, "Static function %s%s%s() cannot be abstract", scope ? ZSTR_VAL(scope->name) : "", scope ? "::" : "", ptr->fname);
}
Dieser Code sagt der nur Ort ein abstract static
darf innerhalb eines interface
ist. Es ist nicht einzigartig für Merkmale, es ist einzigartig in der Definition von abstract static
. Warum? Nun, bemerken es gibt eine leichte Ecke Fall in unserer Definition:
sub-class must implement code for this specific class or any of its sub-classes
Mit diesem Code:
abstract class Foo {
abstract public static function get();
}
Diese Definition bedeutet, dass ich sollte Lage sein Foo::get
zu nennen. Nach allem Foo
ist eine Klasse (siehe das Schlüsselwort "Klasse" dort) und in der strengen Definition, get
soll in dieser Klasse Foo
implementiert werden. Aber klar, das ergibt keinen Sinn, denn nun sind wir wieder bei der Orthogonalität der strikten Statik.
Wenn Sie es in PHP versuchen, erhalten Sie die einzige rationale Antwort möglich:
Cannot call abstract method Foo::get()
So weil PHP statische Vererbung hinzugefügt, es hat mit dieser Ecke Fälle zu behandeln. Dies ist die Natur von Merkmalen. Einige andere Sprachen (C#, Java, usw.) haben dieses Problem nicht, weil sie die strenge Definition übernehmen und abstract static
einfach nicht erlauben. Um diesen Eckfall loszuwerden und die Engine zu vereinfachen, können wir diese "abstrakte statische nur in der Schnittstelle" Regel in der Zukunft erzwingen. Daher E_STRICT
.
würde ich einen Dienst delegieren, um das Problem zu lösen: wenn
I have common method I want to use in several classes. This common method relies on a static method that must be defined externally to the common code.
trait MyTrait
{
public function doSomethingWithSetting() {
$service = new MyService($this);
return $service->doSomethingWithSetting();
}
}
class MyService
{
public function __construct(MyInterface $object) {
$this->object = $object;
}
public function doSomethingWithSetting() {
$setting = $this->object->getSetting();
return $setting;
}
}
fühlt sich ein bisschen Rube Goldberg. Wahrscheinlich würde man sich die Motivation für die Statik anschauen und überlegen, sie zu refaktorisieren.
Ich habe versucht, was Sie wollen in PHP 5.6.10 (CLI) und es hat funktioniert .. Habe ich dich falsch verstanden oder willst du das für PHP 5.4? – Mjh
@Mjh: Was ist Ihre Einstellung ['error_reporting'] (https://secure.php.net/manual/en/errorfunc.configuration.php#ini.error-reporting)? Das obige sollte zu einem "E_STRICT" -Fehler führen. – eggyal
Ich habe die 'error_reporting (E_ALL);'. Ich erklärte ein Merkmal mit 'öffentlichem abstraktem statischem Funktionstest();' und ich erhielt 'PHP strenge Standards: Statische Funktion MyTest :: test() sollte nicht abstrakt im PHP-Shell-Code auf Leitung 1 sein'. Wenn ich eine Klasse erzeuge, die das Merkmal verwendet, und wenn ich die abstrakte Methode nicht implementiere, bekomme ich 'PHP Fatal error: Die Klasse MyTestClass enthält 1 abstrakte Methode und muss daher als abstrakt deklariert werden oder die restlichen Methoden implementieren (MyTestClass :: test) in PHP-Shell-Code in Zeile 1'. Hilft das überhaupt? – Mjh