webentwicklung-frage-antwort-db.com.de

Nicht statische Methode mit Doppelpunkt (: :) aufrufen

Warum kann ich eine nicht statische Methode nicht mit der Syntax der statischen Methoden (class :: method) verwenden? Handelt es sich um ein Konfigurationsproblem?

class Teste {

    public function fun1() {
        echo 'fun1';
    }
    public static function fun2() {
        echo "static fun2" ;
    }
}

Teste::fun1(); // why?
Teste::fun2(); //ok - is a static method
43
NakaBr

PHP ist sehr locker mit statischen und nicht statischen Methoden. Was ich hier nicht sehen kann, ist Folgendes: Wenn Sie eine nicht statische Methode aufrufen, wird ns statisch aus einer nicht statischen Methode der Klasse C heraus aufgerufen, und $this in ns verweist auf Ihre Instanz von C.

class A 
{
    public function test()
    {
        echo $this->name;
    }
}

class C 
{
     public function q()
     {
         $this->name = 'hello';
         A::test();
     }
}

$c = new C;
$c->q();// prints hello

Dies ist tatsächlich ein Fehler, wenn Sie eine strikte Fehlerberichterstattung haben, aber sonst nicht.

30
davidtbernal

Dies ist eine bekannte "Eigenart" von PHP. Es ist beabsichtigt, die Zurückweiterung zu verhindern, um herauszufinden, ob wir vor einiger Zeit tatsächlich ein Objekt instanziiert haben oder nicht (denken Sie daran, PHP wird interpretiert, nicht übersetzt). Beim Zugriff auf ein nicht statisches Member auf den Via-Bereichsauflösungsoperator, wenn das Objekt nicht instanziiert wird, wird jedoch ein schwerwiegender Fehler ausgegeben.

Mit freundlicher Genehmigung von PHP.net:

class User {
    const GIVEN = 1;  // class constants can't be labeled static nor assigned visibility
    public $a=2;
    public static $b=3;

    public function me(){
        echo "print me";
    }
     public static function you() {
        echo "print you";
    }
}

class myUser extends User {
}

// Are properties and methods instantiated to an object of a class, & are they accessible?
//$object1= new User();        // uncomment this line with each of the following lines individually
//echo $object1->GIVEN . "</br>";        // yields nothing
//echo $object1->GIVE . "</br>";        //  deliberately misnamed, still yields nothing
//echo $object1->User::GIVEN . "</br>";    // yields nothing
//echo $object1->a . "</br>";        // yields 2
//echo $object1->b . "</br>";        // yields nothing
//echo $object1->me() . "</br>";        // yields print me
//echo $object1->you() . "</br>";        // yields print you

// Are  properties and methods instantiated to an object of a child class,  & are accessible?
//$object2= new myUser();        // uncomment this line with each of the following lines individually
//echo $object2->GIVEN . "</br>";        // yields nothing
//echo $object2->a . "</br>";        // yields 2
//echo $object2->b . "</br>";        // yields nothing
//echo $object2->me() . "</br>";        // yields print me
//echo $object2->you() . "</br>";        // yields print you

// Are the properties and methods accessible directly in the class?
//echo User::GIVEN . "</br>";        // yields 1
//echo User::$a . "</br>";            // yields fatal error since it is not static
//echo User::$b . "</br>";            // yields 3
//echo User::me() . "</br>";        // yields print me
//echo User::you() . "</br>";        // yields print you

// Are the properties and methods copied to the child class and are they accessible?
//echo myUser::GIVEN . "</br>";        // yields 1
//echo myUser::$a . "</br>";        // yields fatal error since it is not static
//echo myUser::$b . "</br>";        // yields 3
//echo myUser::me() . "</br>";        // yields print me
//echo myUser::you() . "</br>";        // yields print you
?>
23
David Titarenco

Dies ist die Rückwärtskompatibilität von PHP 4. In PHP 4 konnten Sie zwischen einer Objektmethode und der als statische Klassenmethode geschriebenen globalen Funktion nicht unterscheiden. Deshalb haben beide gearbeitet.

Mit den Änderungen im Objektmodell mit PHP 5 - http://php.net/oop5 - wurde jedoch das statische Schlüsselwort eingeführt.

Und dann erhalten Sie seit PHP 5.1.3 strenge Standardwarnungen in Bezug auf solche wie:

Strenge Standards: Nicht statische Methode Foo :: bar () sollte nicht statisch aufgerufen werden

Und/oder:

Strenge Standards: Die nicht statische Methode Foo :: bar () sollte nicht statisch aufgerufen werden, vorausgesetzt, dies ist aus einem inkompatiblen Kontext

die Sie für Ihre Entwicklungsumgebung aktiviert haben sollten. Es ist also nur eine Abwärtskompatibilität zu einer Zeit, in der die Sprache nicht genug voneinander abweichen konnte, so dass dies zur Laufzeit "definiert" wurde.

Heutzutage können Sie es bereits im Code definieren, der Code wird jedoch nicht beschädigt, wenn Sie ihn immer noch als "falsch" bezeichnen. 

Einige Demo zum Auslösen der Fehlermeldungen und zum Anzeigen des geänderten Verhaltens in verschiedenen PHP Versionen: http://3v4l.org/8WRQH

13
hakre

PHP 4 hatte kein statisches Schlüsselwort (im Funktionsdeklarationskontext), erlaubte jedoch weiterhin den statischen Aufruf von Methoden mit ::. Dies wurde aus Gründen der Rückwärtskompatibilität in PHP 5 fortgesetzt.

13
webbiedave

Sie können dies tun, aber Ihr Code wird fehlerhaft sein, wenn Sie $this in der Funktion namens fun1() verwenden.

6
Jake N

WarningIn PHP 7 ist der statische Aufruf nicht statischer Methoden veraltet und es wird eine E_DEPRECATED-Warnung generiert. Unterstützung für das statische Aufrufen nicht statischer Methoden wird möglicherweise in der Zukunft entfernt.

Verknüpfung

4
Malus Jan

In den meisten Sprachen benötigen Sie eine Instanz der Klasse, um Instanzmethoden ausführen zu können. Es scheint, dass PHP eine temporäre Instanz erstellt, wenn Sie eine Instanzmethode mit dem Bereichsauflösungsoperator aufrufen.

1
Jacob Relkin

Nicht sicher, warum PHP das erlaubt, aber Sie möchten sich nicht daran gewöhnen. Ihr Beispiel funktioniert nur, weil nicht versucht wird, auf nicht statische Eigenschaften der Klasse zuzugreifen. 

Etwas so einfaches wie:

<?php
class Foo {

    private $color;

    public function bar() {
        echo 'before';
        $this->color = "blue";
        echo 'after';
    }
}

Foo::bar();

würde zu einem schwerwiegenden Fehler führen

1
brian_d

Ich habe festgestellt, dass, wenn Sie die nicht statische Methode self :: test () von einer Klasse aus aufrufen, keine Warnung für den strengen Standard ausgegeben wird, z. B. wenn Sie Class :: test () aufrufen. Ich glaube, das hat nichts mit LSB zu tun, da meine Klasse nicht erweitert wurde (getestet mit PHP 5.5)?

0
bpile