Note: I'm migrating from gonzalo123.com to here. When I finish I'll swap the DNS to here. The "official" blog will be always gonzalo123.com

      Strange behavior in PHP with method visibility

      Normally I feel very comfortable with PHP, but not all is good. There’s some things I don’t like. One is the lack of real annotations and another one is this rare behaviour with visibility within the OO. Let me explain this a little bit.

      Last week I was refactoring one old script. I removed a coupling problem with DI. Something like this:

      class AnotherClass
      {
          protected function foo()
          {
              return "bar";
          }
      }
       
      class OneClass extends AnotherClass{
          private $object;
       
          public function __construct(AnotherClass $object)
          {
              $this->object = $object;
          }
       
          public function myFunction()
          {
              return $this->object->foo();
          }
      }
       
      $anotherClass = new AnotherClass();
      $oneClass = new OneClass($anotherClass);
       
      echo $oneClass->myFunction();
      

      It works, but I realized that I didn’t need to extend OneClass with AnotherClass (due to the DI), so I removed it. Then the script crashed: Fatal error: Call to protected method AnotherClass::foo() from context ‘OneClass’

      Obviously it was due to the protected function AnotherClass::foo. But, Why it worked when I extends OneClass with AnotherClass? The visibility is the same.

      I reported this “bug” to the PHP community. PHP community is great. I had an answer very quick. It was not a bug. I needed to read several times the answer to understand it but finally did it.

      As someone answer me:

      foo() is protected and was defined in the context of OneClass. The access is done in the context of AnotherClass. AnotherClass is a subclass of OneClass (the context where foo() was defined). Therefore access is granted

      In PHP the visibility belongs to the class not to the instance of the class. I understand the reason, but my mind compute it as a bug :( and it isn’t. It’s a feature.

      What do you think?

      comments powered by Disqus