PHP: What if I call a static method in non-static

2019-01-12 02:20发布

问题:

I'm not pro in Object Oriented Programming and I got a silly question:

class test {
    public static function doSomething($arg) {
        $foo = 'I ate your ' . $arg;
        return $foo;
    }
}

So the correct way to call doSomething() method is to do test::doSomething('Pizza');, Am I right?

Now, what will happen if I call it like this:

$test = new test;
$bar = $test->doSomething('Sandwich');

I've tested it and it's working without any error or notice or etc. but is that correct to do this?

回答1:

As Baba already pointed out, it results in an E_STRICT depending on your configuration.

But even if that's no problem for you, I think it's worth mentioning some of the pitfalls which may result from calling static methods in a non-static way.

If you have a class hierarchy like

class A {
    public static function sayHello() {
        echo "Hello from A!\n";
    }

    public function sayHelloNonStaticWithSelf() {
        return self::sayHello();
    }

    public function sayHelloNonStaticWithStatic() {
        return static::sayHello();
    }
}

class B extends A {
    public static function sayHello() {
        echo "Hello from B!\n";
    }

    public function callHelloInMultipleDifferentWays() {
        A::sayHello();
        B::sayHello();
        $this->sayHelloNonStaticWithSelf();
        $this->sayHelloNonStaticWithStatic();
        $this->sayHello();
    }
}

$b = new B();
$b->callHelloInMultipleDifferentWays();

This produces the following output:

Hello from A!
// A::sayHello() - obvious

Hello from B!
// B::sayHello() - obvious

Hello from A!
// $this->sayHelloNonStaticWithSelf()
// self alweays refers to the class it is used in

Hello from B!
// $this->sayHelloNonStaticWithStatic()
// static always refers to the class it is called from at runtime

Hello from B!
// $this->sayHello() - obvious

As you can see, it's easy to achieve unexpected behaviour when mixing static and non-static method calls and techniques.

Therefore, my advice also is: Use Class::method to explicitly call the static method you mean to call. Or even better don't use static methods at all because they make your code untestable.



回答2:

It is better you call it this way to avoid E_STRICT on some version of PHP

$bar = test::doSomething('Sandwich');

FROM PHP DOC

Static properties cannot be accessed through the object using the arrow operator ->. Calling non-static methods statically generates an E_STRICT level warning.

Also

Declaring class properties or methods as static makes them accessible without needing an instantiation of the class. A property declared as static can not be accessed with an instantiated class object (though a static method can).



回答3:

It makes no difference if your method don't use $this and don't access to static properties.

Static properties cannot be accessed through the object using the arrow operator ->.

$this is not available inside the method declared as static.

But, you should always use :: to call a static method, even through php let you call it on an instance.