Saturday, September 21, 2019

php - Setting private property in super Class from Child class



I have the following classes




  • Abstract class duck
    This class have flyBehavoir of type FlyBehavoir
    Function to perform flying preformFly()
    Function to set flyBehavoir setFlyBrhavoir(FlyBehavoir $flyBehavoir)

  • Class DonaldDuck extends Duck
    in this class, I have a __construct method, inside this constructor, I instantiate new fly behavior FlyWithWings.



The problem is when I need to change flyBehavoir in the runtime via setFlyBrhavoir() method and set it to FlyWithRocket it does not change as long as flyBehavoir is private if I make it public it works fine. how can I do that?



thought that we can change any property in the superclass from the child class, as long as I access this private property vis setter.



below my attempt



 
//abstract class that defines what it takes to be a duck
//inside Duck we will have $flyBehavoir object of FlyBehavoir Type
abstract class Duck{
private $flyBehavoir;

public function preformFly(){
$flyBehavoir.fly();
}
public function setFlyBehavoir(FlyBehavoir $flyBehavoir){
$this->flyBehavoir = $flyBehavoir;
}
}

//creating type FlyBehavoir
interface FlyBehavoir{
function fly();
}

//this concrete class of type FlyBehavoir this will provide our ducks with the functionality they need to fly
class FlyWithWings implements FlyBehavoir{
public function fly(){
echo "I am Flying with my own Wings
";
}
}

//this concrete class of type FlyBehavoir this will provide our ducks with the functionality they need to fly
class FlyWithRocket implements FlyBehavoir{
public function fly(){
echo "I am the fastest duck ever, see my rockets wings
";
}
}


// creating our first duck and given it the ability to fly with wings
class DonaldDuck extends Duck{

public function __construct(){
$this->flyBehavoir = new FlyWithWings;
}

}


$donaldDuck = new DonaldDuck( ) ;

$donaldDuck->flyBehavoir->fly();
//changing behavoir in run time
$donaldDuck->setFlyBehavoir(new FlyWithRocket);
$donaldDuck->flyBehavoir->fly();


Output
I am Flying with my own Wings
I am Flying with my own Wings

Answer



A private property is not accessible in child classes.



class DonaldDuck extends Duck {
public function __construct(){
$this->flyBehavoir = new FlyWithWings;
}
}


For all intents and purposes, this class does not formally declare flyBehaviour at all, so $this->flyBehaviour in the constructor creates a new public property. You can see that clearly when var_dumping the object:



object(DonaldDuck)#1 (2) {
["flyBehavoir":"Duck":private]=>
NULL
["flyBehavoir"]=>
object(FlyWithWings)#2 (0) {
}
}


The parent's private property is a) separate, b) private to it and c) null since nobody has set it yet. Otherwise it would also not be possible for you to access $donaldDuck->flyBehavoir->fly() from without the class!



If you have a private property, you need to only let code of the same class act on it:



class DonaldDuck extends Duck {
public function __construct(){
$this->setFlyBehaviour(new FlyWithWings);
}
}

$donaldDuck = new DonaldDuck();
$donaldDuck->setFlyBehavoir(new FlyWithRocket);
$donaldDuck->preformFly();


This works as you expect, since you're using the correctly privileged methods to access the property. If you want to access the property directly in child classes, it needs to be protected (which then won't let you access it from outside the class though, it would have to be public for that).


No comments:

Post a Comment

hard drive - Leaving bad sectors in unformatted partition?

Laptop was acting really weird, and copy and seek times were really slow, so I decided to scan the hard drive surface. I have a couple hundr...