9

Why is the 'self'-call to a non-satic method in this example working?

class A{

    protected function aNonStaticMethod(){
        return __class__;
    }

    public function aEcho(){
        echo self::aNonStaticMethod();
    }
}

Thanks for explanation.

user2853437
  • 750
  • 8
  • 27
  • As nearly everywhere described and shown in examples (eg http://php.net/manual/de/language.oop5.static.php) self is used in a static method context. I haven't found examples where self is used without a 'public/protected/private/final static function method()'. So may I further like to know, if that use shown above is wrong. – user2853437 Oct 07 '13 at 13:04
  • 1
    `self::` is not limited to static context. Neither is `parent::` nor `SomeParentClass::`. – Kontrollfreak Oct 07 '13 at 13:23
  • 1
    @Kontrollfreak because calling non-static method statically does not make sense in PHP version > 4 ... :-) also it won't be supported in future - check my answer :) – jave.web Mar 11 '16 at 10:35
  • @jave.web Please be aware that I wrote `Some**Parent**Class::` and *not* `SomeClass::`. That means the call to `SomeParentClass::someMethod()` is made from a non-static context that extends `SomeParentClass`. And this would be perfectly valid. – Kontrollfreak Mar 11 '16 at 16:22
  • @Kontrollfreak I was referring to your "Why shouldn't it?" question :) Of course, logically, static calls for static things are for all context - I use it too :) However I've added a note about that to my answer :) – jave.web Mar 12 '16 at 19:04

2 Answers2

8

In your simple example $this and self is interchangable. But be aware of the different method resolving when dealing with inheritance (i added static for completeness):

class A {
    protected function aNonStaticMethod(){
        return __class__;
    }

    public function selfEcho(){
        echo self::aNonStaticMethod();
    }

    public function staticEcho(){
        echo static::aNonStaticMethod();
    }

    public function thisEcho(){
        echo $this->aNonStaticMethod();
    }
}

class B extends A {
    protected function aNonStaticMethod(){
        return __class__;
    }
}

$b = new B();
$b->selfEcho(); // A
$b->staticEcho(); // B
$b->thisEcho(); // B
warly
  • 1,458
  • 1
  • 16
  • 21
7

Calling non-static method statically

Theoretically it should not work, but as this comment says:

There was no static keyword in php4 but php4 did allow for static calls. To maintain backwards compatibility this was left in when the static keyword was added in php5.

This comment is supported by this official php.net wiki:

This is already deprecated if the call occurs from an instance method. Not annotating methods as static is an obsolete PHP4-ism.

You really should not call non-static method statically - it does not make sense (if there is a static keyword).

Avoid calling non-static methods statically completely!

...because a) it is a bad approach and b) the PHP docs say:

Caution
In PHP 5, calling non-static methods statically generates an E_STRICT level warning.

AND

Warning
In PHP 7, calling non-static methods statically is deprecated, and will generate an E_DEPRECATED warning. Support for calling non-static methods statically may be removed in the future.

Using :: operator for non-static calls - may be a good approach!

As @Kontrollfreak pointed out and as this docs say the :: operator is not limited to static calls:

the double colon, is a token that allows access to static, constant, and overridden properties or methods of a class

So it is OK if you reference this way a method or properties from a parent class - which is not limited to a direct parent.

EDIT: do not mistake this for Fascade etc. software patterns!

During writing this answer I forgot to mention that there might be cases, when the call is static, but internally it is calling dynamic method - for more info see patterns like Facade or Singleton.
However do NOT mistake these with issue described above! (issue above is about using direct static call on dynamic thing that should be called dynamically, these patterns are about calling static methods statically, which then may dynamically invoke something dynamic (internally)).

Community
  • 1
  • 1
jave.web
  • 13,880
  • 12
  • 91
  • 125
  • 3
    Even if you're not using `self` or `parent`, the double colon `::` doesn't necessarily mean the call is (or should be) static. How else would you reference a method of a parent class that is not your *direct* parent? See what I mean: [Sandbox Example](http://sandbox.onlinephpfunctions.com/code/e4029741e62fc9761acd9bcf6bce791192baf653) – Kontrollfreak Mar 13 '16 at 13:21
  • @Kontrollfreak Yes, that is true, but only in the way you've described, using it to call class' own non-static method/property is a bad approach :) But thank you for pointing that out - I've added this note to my answer :) Also I've removed the self/parent chapter - I know this approach, I just forgot about it, sorry :P – jave.web Mar 14 '16 at 10:08
  • You write it's bad approach to use `self::` on normal methods. Is that your opinion or can back that claim up? – Kontrollfreak Mar 14 '16 at 18:11
  • @Kontrollfreak - I don't want to be missunderstood - using self:: is bad approach **only** if you reference **class'-own** ***non-***static method - it is explained in the first part of my answer, but also in the latter one - "static, constant and overriden..." - since calling class' own non-static-non-constant things is not overriding nor constant calling nor static calling - using `::` operator itself does not fit into this definition, Calling "my own" non-static should be done through `->` ... So answer to both of your questions is yes - I think so & docs support what I say. – jave.web Mar 14 '16 at 19:50
  • 3
    I think you're mixing the issues here. Yes, [the docs](http://php.net/manual/en/language.oop5.static.php) say calling non-static methods statically is deprecated. But using `self::someNonStaticMethod()` **isn't** a static call. Using `self::` is *more specific* than using `$this->`, as the former always refers to its origin class. I prepared another example with [`self::`](http://sandbox.onlinephpfunctions.com/code/de2edb50a2b409b92d7714ea10b6014673176103) and [`$this->`](http://sandbox.onlinephpfunctions.com/code/4757589885dcbd796e9bd41ed23a25f33adaf9b4) to show the difference. – Kontrollfreak Mar 16 '16 at 15:27
  • @Kontrollfreak Well that is sort of overriding - but backwards - so you are right on this one - however it still **does** fit to what I said... What I mean is if you would really call your own not-overriden (in any way) method with `::` - that whould be wrong. – jave.web Mar 16 '16 at 19:37
  • Indeed, it is a difference between $this-> and self:: for non static calls. However, even if it works, using it is a bad practice. When you extend a class, you expect that the functions you override will be used. An extended class should not behave in a way that is unpredictable. It hides multiple responsibilities behind the name of a function. It would be cleaner to just have a private method you call with this if you do not intend to have it overwritten. For those reasons, this language feature is unsafe to use, especially in a team, because it brings no real value, but adds complexity. – Ovidiu Badita Feb 07 '18 at 14:19