Bojan Dević
Bojan Dević

Reputation: 1875

PHP inheritance, parent functions using child variables

While reviewing some PHP code I've discovered a strange thing. Here is the simple example illustration of it:

File A.php:

<?php
class A{
    public function methodA(){
        echo $this->B;
    }
}
?>

File B.php:

<?php
    class B extends A{
        public $B = "It's working!";
    }
?>

File test.php:

<?php
    require_once("A.php");
    require_once("B.php");
    $b = new B();
    $b->methodA();
?>

Running test.php prints out "It's working!", but question is why is it working? :) Is this a feature or a bug? Method methodA in class A can also call methods that are in class B which should not work in OOP.

Upvotes: 14

Views: 3429

Answers (8)

hakre
hakre

Reputation: 197624

$this is just an object variable - a special one because it's the current one, but it still is just an object variable.

Because $B::B is a public member variable, it can be accessed from everwhere a reference to the instance of B is reachable, e.g. with a object variable.

As public members are accessible everywhere, any function, even from within A::methodA() it can be accessed.

So there is not much to actually wonder about. Class inheritance in your example only relates to the (invisible) passing of the object variable in form of the $this "parameter" when A::methodA() is invoked.

See the following example that probably makes it more visible:

function methodA($object) {
    echo $object->B;
}

class B {
    public $B = "It's working!";
    public function methodA() {
        methodA($this);
    }
}

Upvotes: 3

Justin ᚅᚔᚈᚄᚒᚔ
Justin ᚅᚔᚈᚄᚒᚔ

Reputation: 15369

This is how OOP is supposed to work. It might seem a little odd at first, since you'd think that A would have to know what $this->B is first (and indeed in some languages this would produce a compiler warning), but the behavior is correct since the subclass you're using is defining the variable that your function is looking for. If you called methodA() from an instance of A(), then you'd get an "undefined" error.

Now, what would be weird (read: wrong) is if THIS worked:

class A {
   public $b = "Derp";
}
class B extends A {
  function sayIt() { echo $this->b; }
}
$a = new A();
$a->sayIt();

Upvotes: 1

halfer
halfer

Reputation: 20430

That makes sense to me; $B is made available in the resultant object by virtue of its appearing in class B. Since $this->B is evaluated at run-time, and the value is set before that (when class B is instantiated) it is found to be set correctly.

You can do this with methods as well, since their existence is not checked until they are executed (although it is usual in the case of methods to declare them abstract in the parent class, thus forcing the child to implement them).

Upvotes: 1

EricSchaefer
EricSchaefer

Reputation: 26330

PHP is a dynamic language. When methodA() is called on an instance of B the B's member $B does actually exist.

$a = new A();
$a->methodA();

would not work.

In some dynamic languages you can even define methods at runtime.

Upvotes: 1

PinnyM
PinnyM

Reputation: 35533

As PHP is a dynamic language, there is nothing wrong with calling properties or methods that may exist on the instance that is using it (in this case an instance of subclass B)

Upvotes: 2

Ali
Ali

Reputation: 267049

Class B extends from Class A, hence it inherits the method methodA() from class A.

Upvotes: 0

Brad
Brad

Reputation: 163270

You're only instantiating class B. Ignore A for the moment, and pretend that methodA() is part of class B.

When class B extends A, it gets all of A's functions. $this->B isn't evaluated until the code is running, not prior. Therefore no error occurs, and won't occur as $this->B exists in class B.

Upvotes: 12

Muhammad Hasan Khan
Muhammad Hasan Khan

Reputation: 35126

PHP is a dynamic language. The methods and data members are evaluated at runtime. When you call a method or access a member, PHP actually looks up a hashtable of sort to find out whether this method or member can be accessed on this object or not which can be anywhere in the inheritance hierarchy.

And not just inheritance, you can always assign arbitrary data to an object on runtime and the code inside the class will still be able to access it using $this->something where 'something' didn't even exist in class.

Upvotes: 6

Related Questions