Class inheritance/visibility

the PHP manual says

. Members declared protected can be accessed only within the class itself and by inherited and parent classes.Members declared as private may only be accessed by the class that defines the member.

This actually works. That is if I declare something protected or private, it can not be accessed from an instance (ala $a->prop; ). And when I declare something as private it can only be withing the class itself and , theoretically and functionally , is not passed on to any extensions of the root class. In practice this seems to work: if I declare $prop as private $this->prop will not work in a child class ( unless I declare another private $prop within that child class).

Ok by now you are saying well if you are going to do that then why not make $prop protected instead of private? Actually i usually do, although sometimes it seems if I have many nested classes and I just want a couple of them tho have access to $prop that it is logical to make $prop private so that it is not inherited by child classes. again this works, functionaly.

My question is about something I noticed via var_dumps of objects.

		class Test1{
		public 		$tesVar	=	'Veronica';
		public 		$hold	=	array();
		protected 	$name	=	'';
		public 		$another=	'other';
		private 	$births	=	'Test2';
		private 	$OnlyHere	=	'only once';

		function Test1($name){
			$this->name=$name;
		}
		function output (){
				foreach ($this as $k=>$that){
					echo $k,'=',$that,'<br>';
				}
				if (isset($this->OnlyHere)) {echo $this->OnlyHere.'<br>';}
				else {echo "just chickens!";}
				echo    '<b>I produce ', (($this->births) ?$this->births:'nothing'),'</b><br>' ;
				echo '-----<br>';
		
		}
		function makeChild ($name="anonn"){
			if($this->births)  { 
				$this->hold[$name]=new $this->births($name);
				return $this->hold[$name];
			} 
			return false;
		}
	}
	class Test2 extends Test1{
		private 	$births		=	'Test3';
	}
	class Test3 extends Test2{
		private 	$births		=	false;// neuters class
	}
	
	$Test1=new Test1('Start');

	$Test1->tesVar="And Ray";
	$Test1->makeChild("first");
	$Test1->hold['first']->makeChild('second');
	echo'<pre>';
	$Test1->hold['first']->output();
	var_dump($Test1);


When property is PRIVATE it still appears in the var_dump of descendant objects, even if it was NOT declared in their classes ( I would expect this for PROTECTED, but not for PRIVATE). This is … the property isnt accessible… but it APPEARS to be set anyway?!?

Even weirder, if you re declare a private property so that it has a different value… then you have MULTIPLE intances of the same property ( again only the one recently declared is actually accessible form the class… but its still weird)


object(Test1)#1 (5) {
  ["tesVar"]=>
  string(7) "And Ray"
  ["hold"]=>
  array(1) {
    ["first"]=>
    object(Test2)#2 (6) {
      ["births:private"]=>
      string(5) "Test3"
      ["tesVar"]=>
      string(8) "Veronica"
      ["hold"]=>
      array(1) {
        ["second"]=>
[I]        object(Test2)#3 (6) {
[B]          ["births:private"]=>
          string(5) "Test3"[/B]
          ["tesVar"]=>
          string(8) "Veronica"
          ["hold"]=>
          array(1) {
            ["anonn"]=>
            object(Test2)#4 (6) {
              ["births:private"]=>
              string(5) "Test3"
              ["tesVar"]=>
              string(8) "Veronica"
              ["hold"]=>
              array(0) {
              }
              ["name:protected"]=>
              string(5) "anonn"
              ["another"]=>
              string(5) "other"
[B]              ["births:private"]=>
              string(5) "Test2"[/B]
            }
          }[/I]
          ["name:protected"]=>
          string(6) "second"
          ["another"]=>
          string(5) "other"
          ["births:private"]=>
          string(5) "Test2"
        }
      }
      ["name:protected"]=>
      string(5) "first"
      ["another"]=>
      string(5) "other"
      ["births:private"]=>
      string(5) "Test2"
    }
  }
  ["name:protected"]=>
  string(5) "Start"
  ["another"]=>
  string(5) "other"
  ["births:private"]=>
  string(5) "Test2"
}


This ‘semi-duplication’ doesn’t occur if the property is set to PROTECTED instead of PRIVATE, still it doesn’t seem to be logical either way.

ALSO
In my test ‘only once’ should never be echoed since the property that contains it is PRIVATE and not inherited by child classes.
I would have expected, that in any object , BUT one of class TEST1, that isset( $this->OnlyHere) would be false.

Actually, it’s even more convoluted than that. What seems to be happening is the INHERITED FUNCTIONS ( output()), are executed in the root class and not at the instance class, and as such they also have access to all the PRIVATE root class properties. The solution would be to rewrite the EXACT SAME function within the first child class. But doesn’t that negate the point of OOP?

Could some one shed some ( simplified) light on this subject?

It’s working exactly the way it should be. Setting a property to private will does not stop it from being inherited. It is still instantiated and assigned a value by the root class. The only difference between private and protected is whether or not a child class has direct access to it’s value. In your example, the output() function is echoing all variable within its scope.

For instance, think about the way get and set functions work. They allow access to a private member variable by a child without allowing direct access to the value itself. If a parent function does not have access to the values within its own scope then there would be no reason for it to exist.

For example:

<?php

class Test1 {
    
    private $name;
    
    public function __construct(){}
    
    public function set( $name )
    {
            $this->name = $name;
    } 
    
    public function getName()
    {
        return $this->name;
    }
    
    public function parentOutput()
    {
        echo $this->name . '<br />';
    }
    
}

class Test2 extends Test1 {
    
    public function __construct( $name ) 
    {
        $this->set( $name ); // works because it is a function defined in the parent and retains access to parent variable. 
       
    }
    
    public function childOutput()
    {
        echo $this->name . '<br />'; // will no work because the value exists but is invisible in the current scope.
    }
    
    
}

$test = new Test2( 'John Doe' );
$test->parentOutput(); // will display the name 
$test->childOutput(); // will cause an error

Calling the output method will display the name because the function was declared in the parent class and retains access to all parent member variables.

Calling the childOutput method will throw an error because it is declared in the child class. Even though it inherits the name variable it cannot see it or access it without the use of the getName function.

However, if we re-write the childOutput to the following it will work, because the getName function retains access to the name variable.


    public function childOutput()
    {
        echo $this->getName() . '<br />'; // value access through parent function
    }

Does this help at all?

It’s working exactly the way it should be. Setting a property to private will does not stop it from being inherited.The only difference between private and protected is whether or not a child class has direct access to it’s value.

That’s what I was trying to confirm. It made sense to me from the onset, but it also seemed ‘wasteful’ as inaccessible properties still get stored in child classes ( if that’s makes sense)

I do have ONE QUESTION remaining, and that is inherited method seem to act as if they were in the parent class ( and as such they have access to properties or property values set at the parent scope

Perhaps this is not what inheritance was meant for and am wrong for thinking this way… which was that an inherited method had teh current scope, not the scope of the parent. The reason I find it cumbersome otherwise is because( as you essentially utilized this in your example) the magic variable $this->… will always point to the class from which the method was inherited and NOT the current class… unless the method is copied in the new class ( which really doesnt do much for cutting down code or redundancy.

This is what I mean:



class Test1 {

    private $name;
    private $value= 10;
    public function output()
    {
        echo $this->value . '<br />'; //
    }

}
class Test2 extends Test1 {
   private  $value=5; // for the sake  of example, lets say $value must be '5' anytime an intance of Test2 is dealt with.
}

$test = new Test2();
$test->output(); // will display the 'value' property of the class ; one would expect '10' if Test1, '5' if Test2.



This works, however if we rewrite the function again in the child class ( of course doing so defeats any attempt at code frugality and makes the code redundant)

 class Test1 {

    private $name;
    private $value= 10;
    public function output()
    {
        echo $this->value . '<br />'; //
    }

}
class Test2 extends Test1 {
   private  $value=5;
    public function output()
    {
        echo $this->value . '<br />'; //
    }

}

$test = new Test2();
$test->output(); // will display the 'value' property of the class ; one would expect '10' if Test1, '5' if Test2.



It seems a simple enough fix to just make $value protected , instead of public, but what if $value is not supposed to be present at all in TEST 2?



class Test1 {

    private $name;
    private $value= 10;
    public function output()
    {
        echo $this->value . '<br />'; //
    }

}
class Test2 extends Test1 {}
$test = new Test2();
$test->output();

I still outputs 1) and unsetting $value in Test2 wouldn’t help, as the function is actually running in Test1 and acting on the properties of Test1, even tho its an instance of Test2. I hope my question makes sense…

If Test2 should not have $value, then you shouldn’t be inherting from a class that contains $value (ie: Test1). Inheriting means you take on all methods and variables from the class you are extending. You must take on private variable as the methods in the inherited class may require the use of those private variables.

Now when you re-defined output(), you actually overwrote the base method for output in Test1, so when you had an instance of Test2()->output() you ran the output defined within Test2() instead of Test1() because you overwrote it.

Extending is best summed up by the following example (at least it has always helped me:


class Animal
{
  private $fed = false;
  protected $type = "Unknown";
  public function MakeNoise()
  {
    echo "No Noise Defined";
  }

  public function GetType()
  {
    echo "Type of " . $this->type;
  }

  public function FeedMe()
  {
    $this->fed = true;
  }

  public function HasBeenFed()
  {
    return $this->fed;
  }
}

class Dog extends Animal
{
  public function __construct()
  {
    $this->type = "Dog";
  }

  public function MakeNoise()
  {
    echo "Woof Woof";
  }
}

class Cat extends Animal
{
  public function __construct()
  {
    $this->type = "Cat";
  }

  public function MakeNoise()
  {
    echo "Meow Meow";
  }
}

$dog = new Dog();
$dog->GetType(); // Type of Dog
$dog->MakeNoise(); // Woof Woof
$dog->HasBeenFed(); // false;
$dog->FeedMe();
$dog->HasBeenFed(); // true;
$cat = new Cat();
$cat->GetType(); // Type of Cat
$cat->MakeNoise(); // Meow Meow
$cat->HasBeenFed(); // false;
$cat->FeedMe();
$cat->HasBeenFed(); // true;
$animal = new Animal();
$animal->GetType(); // Type of Unknown
$animal->MakeNoise(); // No Noise Defined
$animal->HasBeenFed(); // false;
$animal->FeedMe();
$animal->HasBeenFed(); // true;

Both Dog and Cat, can’t access $this->fed, but calling HasBeenFed and FeedMe both need and have access to $this->fed.

I never really thought about it that way. The thing with PHP is that it allows us to get away with a lot that we would not be able to with a strictly typed language.

When inheriting a class the parents constructor should always be called explicitly. The child the does not magically gain access to the methods in the parent class. It must first create an accessible instance that it can use. So really, even though the parents methods are accessible by the child, they must still operate within their own scope. The parent has no idea that it has been inherited or extended and it acts as such.

Another thing to keep in mind is that you can always access a method that has been overridden using the parent:: operator.


<?php

 class Test1 { 
     
    private $value = 10; 
    
    public function __construct( $value )
    {
        $this->value = $value;
    }
    public function output() 
    { 
        echo 'Test1\\'s value is ' . $this->value . '<br />'; // 
    } 
} 

class Test2 extends Test1 { 
    private  $value = 5;    

    public function __construct( $value )
    {
       parent::__construct( $value );
       $this->value = $value * 2;
    }
    public function output() 
    { 
        parent::output(); // outputs 5
        echo 'Test2\\'s value is ' . $this->value . '<br />'; // outputs 10
    }   
}

$test = new Test2( 5 ); 
$test->output(); 

Also as cpradio said, if you are extending a class that has values you don’t need then the object architecture you are using should be re-evaluated. The beauty of programming is that you can make it work in whatever way will work best for you.

True words. I messed up in my example, my construct for Dog and Cat should have parent::__construct(); in them. Good catch JeremyC

This isn’t really a question, but the description is correct. A method has access to only those private fields that were declared within that method’s class block.

The reason I find it cumbersome otherwise is because … the magic variable $this will always point to the class from which the method was inherited and NOT the current class

Only when it comes to private fields. Private fields are kind of like local variables. They live in their own little bubble, and nothing outside can touch them. On the other hand, fields that are protected or public can be redefined by subclasses.

OK… that works…

But you must admit the syntax parent:: output(); // outputs 5 seems backwards. I mean I would have never thought of having child output call parent output using “parent::” as I woudl have assumed “parent::” INVOKED the parent scoped ( not to mention it an extra 3 lines) I would have figured the ‘default’ behaviour would be the child fuction had the child scope and IF you needed the parent scope you would have used :: parent.

As arbitrary as it would seem… I think i do get how it works now… thank you.

You are correct, parent:: should only be used if you need to access the parents functionality of an overridden method. The only reason that I put it in the childs output() method was to try and demonstrate how it worked, it was not necessary by any means. I’m sorry if that seemed confusing.

Some advice I took eons ago when designing classes/objects. Never use public or private on properties, always protected. By not using public you keep the properties encapsulated from the outside world, allowing only the object to change them. By not using private you don’t hinder inheritance. Then you don’t have this complex mess like we are discussing now. (Side note, public and protected is all I use on methods. I never use private for anything.)

Can you describe a situation that is part of your ‘complex mess’; what specifically are private properties causing in your situation?

ServerStorm,

I was thinking the same thing. I use private methods and variables a lot with my architectures, to simplify methods, such as, I may have a private method that does nothing but resize a larger provided image into a thumbnail (no need to expose this method to extended classes or to the public, as the public just needs to provide a large image).

So I too am curious why a recommendation would be made to not use private for anything…

One of the benefits of objects is inheritance, using private disrupts that ability. I have yet to hear a single case where using private offers any benefit other then hampering inheritance.

The case both for and against private vs protected: http://fabien.potencier.org/article/47/pragmatism-over-theory-protected-vs-private

Thank you.

Interesting read and not what I expected to hear from Fabien Potencier. Thanks also for this.

Steve

Correct me if I am wrong, but wasn’t the point of this article stating that someone who previously never used private for anything, now does, and supports so as it helped his API? All the comments in support for not using private again, just scream it hinders inheritance but with no real proof.

Maybe, I work too often in APIs where you only expose what is meaningful and makes sense and nothing more. I primarily write components that are interacted with by third parties or services within the local company, so I am constantly asking myself (is this something someone would want/need to override?) If the answer is not a 100% yes, it gets marked as private until a use case comes around asking for it, then I can safely change it to protected/public without breaking prior versions (I rarely have this situation, as typically what I expose allows them to do what they need in a cleaner more realistic approach).

So did I miss something on why protected is valued more than private? I really want to know more about that point of view with more than “it hinders inheritance”. Give me a real case scenario where you used a private method (and you without any hesitation determined it would not or ever need to be extended) and so you had to switch it to protected/public.

Hi cpradio,

You interpreted the point of the article correctly, and also most of the comments disagreed. This should not confuse Fabien’s point, which is ‘He used to avoid, even ban the use of private, but due to community team members views and their use of private surprised Fabien as it created clearer API’s’. From what I read in your post, you are using private in a similar way. You could look to your own examples ->

.

Steve

Unfortunately, the only examples that I have were from early on in my career, where I made incorrect assumptions. I was just trying to see if there are other reasons that I am missing, or general discussion. I’ve learned two things early on in my career 1) never flat out say that something shouldn’t be used; ever. 2) never say you should always do X vs Y.

There are reasons for the existence of types, functions, patterns, etc. You are bound to encounter the correct reason for something that was barred at some point, know when to use something and when you shouldn’t, and when unsure, research it and ask around.

I am simply trying to learn the mindset that is set against private, as in 1) how did it solve your problem, and 2) what was the after-math, have you had bugs because you exposed a method that someone overrode incorrectly? (or more likely, that a future API broke because it changed the implementation); did things just go much smoother? how so? etc.

Hi cpradio,

I don’t use private very often because it has got in my way when extending object. I am not of the mindset that private is bad it just affects the way I currently code (Although I would be the first to admit that I am not the best OOP programmer here, so I think I don’t best understand how it would improve what I do). I can see if you have a class that gets extended and part of it you don’t want it to be overwritten and maybe only provide a getter/setter for it then you would declare it private.

I looked at the solution that Fabien linked to in the article but I could not see how it helped or hindered, but I did see how it forced them to refactor one method into three methods, so maybe that was his point.

Maybe someone else will have a good example.

Steve

Some answers and self evolvement only come by repeating the same question at the occurance of another answer to force analysis of the subtleties of the original question.

At a technical level “override method” has become an allowable answer due to inheritance and protected methods. The deeper question is why override method and messing with inheritance chains was required and whether having to tamper was a sign of another deeper design issue.

A lot of the muddiness of this topic comes from the confusion that inheritance(a technical implementation detail) is equal to polymorphism/Liskov substition principle(an external communication/interface detail).

Anyway I would point that the real answers lie outside of the PHP community as it has a habit of repeating everything our ancestors did however unclean for the sake of self experience sometimes unknowingly rebranding a bad practice with a cool new name. There is decades of information and experience to glean on this topic.

For gleaning random subjective experience programmers stack exchange is always a good daily read.

Hint. override method as the most ideal/quick opportunistic answer usually comes from the act of favouring inheritance over composition combined with a muddling of responsibilites.
http://programmers.stackexchange.com/questions/65179/where-does-this-concept-of-favor-composition-over-inheritance-come-from