Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP: override parent class properties from child class

Maybe you know some "right-way" to override class property from child class method

<?php
class A {
  public $option;
  public function __construct() {
    $this->option = array(1,2,3);
  }

  public function bb() {
    $obj = new B;
    $obj->aa();

    print_r($this->option);die;
  }
}

class B extends A {

  public function __construct() {
    parent::__construct();
  }

  public function aa() {
    $this->option[] = 4;
    //print_r($this->option);die;
  }
}

$obj3 = new A;
$obj3->bb();
?>

returns Array ( [0] => 1 [1] => 2 [2] => 3 ) without elemnt from method aa()

Is it possible to override parent class property from child class?

like image 583
Igor Sazonov Avatar asked Mar 28 '14 20:03

Igor Sazonov


1 Answers

The problem is that you are trying to do something in a way it is not at all meant to be done. It is a little difficult to tell what you are trying to do but hopefully if you look at my sample it will show you what is happening:

<?php

class BaseClass {
    /* If a property is public or protected it can be overriden in derived classes.
     * If you had made it private it wouldn't be changable in derived classes. 
     * If you make it also make it static then there is only one copy of it shared 
     * by all instances of the class (as well as those derived from it). */
    protected $option=array();

    public function __construct() {
        $this->option=array(1,2,3);
        /* We are in the base class so the reset() method doesn't exist yet.
         * This fails in this class: */
        // $this->reset();
    }
    /** Print the $option variable. */
    public function dump() {
        echo sprintf('<pre><b>%s</b> = ', get_class($this));
        print_r($this->option);
        echo "</pre>\n";
    }
}

class DerivedClass extends BaseClass {
    public function __construct() {
        parent::__construct();
        /* We have complete control over the variable BaseClass::$option from this class.
         * If we want to we can even make it a string instead of an array. */
        $this->option="I've overridden the option property.";
    }
    /** Reset the BaseClass::$option variable. */
    public function reset() {
        $this->option=array(1,2,3,4);
    }
}

/// Create a few test objects to play with
$objBase=new BaseClass();
$objDerived=new DerivedClass();

$objBase->dump(); // Display the base object data

/// If BaseClass::$option is public you can edit it directly here.
/// This may be easier but it is discouraged because it breaks OOP principals.
//$objDerived->option[]=5;

$objDerived->dump(); // Display the derived object data

$objDerived->reset(); // call a method which will change our data
$objDerived->dump(); // Display the derived object data again now

Classes give many ways to further control what can be seen by those classes derived from the current class and externally. This is done by using the public, protected and private keywords. When set to public, methods and properties are visible to everything but they can still be out of scope. In short, the only problem you had was that your method B:aa() was out of scope in A::bb().

Remember that in reality BaseClass may not be in the same file as DerivedClass and some projects may not need DerivedClass. If you keep that in mind it should make sense that you can't use methods which aren't even being loaded into the project.

In your code you are making a whole new instance of B in the method A::bb(). This is a design pattern which you will almost never see except in a few specific types of functions (called factory functions because they are meant for creating derived classes from within a base class on purpose). I'm fairly sure that is not what you are doing here because that is not something you do in PHP very often because PHP doesn't usually read binary class data from files and in other situations there are usually better ways to get things done.

like image 73
krowe Avatar answered Oct 07 '22 08:10

krowe