class parents{
public $a;
function __construct(){
echo $this->a;
}
}
class child extends parents{
function __construct(){
$this->a = 1;
parent::__construct();
}
}
$new = new child();//print 1
This code above print 1,which means whenever we create an instance of a child class,and assign value to properties inherited from its parent,the property in its parent class also has been assigned.But the code below shows different:
class parents{
public $a;
function test(){
$child = new child();
echo $this->a;
}
}
class child extends parents{
function __construct(){
$this->a = 1;
}
}
$new = new parents();
$new->test();//print nothing
Where I assign value to its child class and the parent apprently didn't have the value it assigned to its child class,why?
Thanks!
In the top example, since the construct function is being called from the child class, it is treating the object being used as if it were the child object that is just using a function in the parent class as if it were it's own.
In the bottom example you have two separate objects acting independently. The parent object has it's $a and so does the child, but they are not the same $a since they are contained in separate objects. so when you print $this->a in the parent class, it is referring to the parent's instance of $a whereas if you echo $a after setting $this->a =1 in the child class it would display the child's instance of $a.
Hope this cleared some stuff up for you.
You are mixing object composition and class inheritance.
Inheritance (realized through the extends keyword) defines an is a relationship.
Composition defines a has a relationship.
To illustrate this concept we will start with inheritance.
class Person {
public $name;
public function talk(){};
public function poop(){};
}
class Parent extends Person {
public function __construct($name) {
$this->name = $name;
}
}
class Child extends Person {
public function __construct($name){
$this->name = $name;
}
}
In this example we are defining a class of things called People. From that definition we are deriving two different subtypes of People, Parent and Child. When we subtype a class then the subtype gains it's own copy of all of the properties and has access to all of the methods defined in the base type, so without defining it a Child and Parent have a name and can both talk and poop by virtue of also being a person.
For example:
$parent = new Parent("Homer");
$child = new Child("Bart");
$parent->talk();
$child->poop();
Composition is used when you want to implement a has a relation ship. Lets revise our type definition of Parent.
class Parent extends Person {
public $children = array();
public function __construct($name) {
$this->name = $name;
}
public function addChild(Child $child){
$this->children[] = $child;
}
}
What we have now allowing if for a Parent to have a child.
$parent = new Parent("Homer");
$child = new Child("Bart");
$parent->addChild($child);
// now I can access homers first child
echo $parent->children[0]->name;
When you instantiate parent, the instance of child created extends the parent class with to test() function. However, that doesn't change the value of $a.
That happens, because you have two different instances, which have nothing in common(except the the inheritance..)
The behavior you except could be generated with inner classes - which php don't support.
If you want to share an var accros every instance, you have to make it static
class parents{
public static $a;
function test(){
$child = new child();
echo self::$a;
}
}
class child extends parents{
function __construct(){
self::$a = 1;
}
}
$new = new parents();
$new->test();
which isn't probably what you want. Or you tell exactly, where you want to change your var
class parents{
public $a;
function test(){
$child = new child();
echo $child->a;
}
}
class child extends parents{
function __construct(){
$this->a = 1;
}
}
$new = new parents();
$new->test();
It's because in the first example you instantiate child
$new = new child();//print 1
and in the second you instantiate parents
$new = new parents();
The second works the same as the first using $new = new child();
If you want to access $a by instantiating child() you need to do it like this:
class parents{
public $a;
function test(){
$child = new child(); //CHANGE HERE
echo $child->a;
}
}
class child extends parents{
function __construct(){
$this->a = 1;
}
}
$new = new parents();
$new->test();
Related
Declare a private property on a Parent class, and then redeclare that property as public or protected on a Child class.
When you create an instance of the Child class, and invoke a method that is inherited from the Parent class. The property on the Parent class is used, and not the property on the Child class.
This is not the case if the initial declaration of the property on the Parent class is public or protected.
Could someone explain to me why this is?
<?php
class P {
private $foo = 'bar';
public function e()
{
echo get_class($this);
echo "\n";
echo $this->foo;
echo "\n";
}
}
class C extends P
{
protected $foo = 'baz';
}
$parent = new P();
$child = new C();
$parent->e();
$child->e();
Output:
P
bar
C
bar
Expected Output:
P
bar
C
baz
Private properties are, as the name implies, private. This means they only be accessed from within the class. As others have mentioned in the comments, this question offers a very good in depth explanation of variable scope in PHP, so by all means go check it out, it's an interesting read.
In your specific however, you seem to be concerned about renaming/overloading variables in a child class. More specifically, we're looking at what happens when a parent and child class happen to both have a property of the same name, and the parent class has a function which return that property.
class A {
private $foo = 'bar';
public function getFoo() {
return $this->foo;
}
}
class B extends A {
protected $foo = 'something something';
}
$b = new B;
echo $b->getFoo();
In the example above, the output would be bar, and that's actually the expected behavior. Since the function getFoo is not overwritten in the child class, PHP executes the function in the parent class. When it gets there, $this refers to A and therefore prints the value of $foo as it is defined in A. It's interesting to note that in this specific example, the scope of B::foo does not matter. In fact, it could omitted entirely and the code would still run perfectly fine.
We can experiment with different function scopes and see what happens:
class A {
private $foo = 'bar';
public function getFoo() {
return $this->foo;
}
private function getCapitalizedFoo() {
return strtoupper($this->foo);
}
protected function getDoubleFoo() {
return $this->foo . $this->foo;
}
}
class B extends A {
protected $foo = 'something something';
public function getParentDoubleFoo() {
return parent::getDoubleFoo();
}
}
$b = new B;
echo $b->getFoo().PHP_EOL; // Output: bar
echo $b->getParentDoubleFoo(); // Output: barbar
echo $b->getDoubleFoo(); // Output: Uncaught Error: Call to protected method ...
echo $b->getCapitalizedFoo(); // Output: Uncaught Error: Call to private method ...
Now, the question remains: How can you access private members from a parent class?
If you have read on the subject, you probably know that, unless completely necessary, your object's properties should be private so as to encapsulate its logic and data as much as possible. Knowing that, the best to allow a child class to access and modify its parent's class properties is by creating accessors and mutators for them.
class A {
private $foo = 'foo';
private $bar = 'bar';
public function setFoo($foo) {
$this->foo = $foo;
}
public function getFoo() {
return $this->foo;
}
protected function setBar($bar) {
$this->bar = $bar;
}
protected function getBar() {
return $this->bar;
}
}
class B extends A {
public function __construct() {
parent::setFoo('more foo');
parent::setBar('more bar');
}
public function getCapitalizedFoo() {
return strtoupper(parent::getFoo());
}
public function getCapitalizedBar() {
return strtoupper(parent::getBar());
}
}
$b = new B;
echo $b->getCapitalizedFoo(); // Output: MORE FOO
echo strtoupper($b->getFoo()); // Output: MORE FOO
echo $b->getCapitalizedBar(); // Output: MORE BAR
echo strtoupper($b->getBar()); // Output: Uncaught Error: Call to protected method ...
By creating public functions to access and modify the parent class' properties you allow the child class to overwrite them and perform logic of its own without having to duplicate the variable. However this also means that any instance of B can potentially alter the values defined in A. In order to mitigate this, you can create protected function that will allow B to internally access and consume the parent class attributes, but the code that consumes B will not be able to do the same.
Basically this is what i want to do:
<?php
class App {
public $var = "main-class";
public function load() {
$this->var = "child-class";
$child = new Child;
$child->echo_var();
}
}
class Child extends App {
public function echo_var() {
echo $this->var;
}
}
$app = new Child;
$app->load();
?>
It outputs "main-class", i want it to output "child-class" without having to modify the child class (because i want it to be sort of a "clean" and dynamic class).
I accept suggestions for another course of action
PS: This is part of an Small MVC Framework i'm trying to develop.
There are two ways that you could do this. Both are going to need to use constructors. With the first one, the child will declare itself when created
<?php
class App {
public $var = "main-class";
public function __construct($var=null) {
if($var !== null) {
$this->var = $var;
}
}
public function load() {
$child = new Child ();
$child->echo_var();
}
}
class Child extends App {
public function __construct(){
parent::__construct("child-class");
}
public function echo_var() {
echo $this->var;
}
}
$app = new Child();
$app->load();
?>
The second one allows the parent to declare the name of the child.
<?php
class App {
public $var = "main-class";
public function __construct($var=null) {
if($var !== null) {
$this->var = $var;
}
}
public function load() {
$child = new Child ("child-class");
$child->echo_var();
}
}
class Child extends App {
public function echo_var() {
echo $this->var;
}
}
$app = new Child();
$app->load();
?>
Both of those examples work and do what you want, I believe.
This isn't how inheritance works - By creating a new Child object, its data members are all initialized with their default values. When you do $this->var = "" in the parent class, you're setting the data members for the $app object, not the $child object.
You can modify the child class to incorporate a constructor that accepts parameters, and that constructor would set its data members properly. To achieve something similar to what you want, you can use constructors:
<?php
class App {
public $var = "main-class";
public function __construct() {
$this->var = "child-class";
}
public function load() {
$child = new Child;
$child->echo_var();
}
}
class Child extends App {
public function __construct()
{
parent::__construct();
}
public function echo_var() {
echo $this->var;
}
}
$app = new App;
$app->load();
I find it very strange that your parent class instanciates it's child. Generally, you would instanciate the child, and you get all the functionality of the parent.
$app = new Child();
$app->load();
The problem is that you actually have 2 different instanciations. You have an object of App and it's holding a separate object of Child.
The other way to do this would be to make $var a static variable and then it would be available independent of the instantiation. I don't generally recommend making properties static though. It's generally considered bad form (for numerous reasons).
PHP
If I create a new instance of a parent class and a new instance of a child class, how can I change the variable in the parent class directly and view the change in the child class?
Take the following code:
class parentClass {
public $varA = 'dojo';
public function setVarA() {
$this->varA = 'something grand';
}
public function getVarA() {
return $this->varA;
}
}
class childClass extends parentClass {
public function useVarA() {
echo parent::getVarA();
}
}
$parentInstance = new parentClass();
$childInstance = new childClass();
$initialVarA = $parentInstance->getVarA(); // should set $initialVarA variable to 'dojo'
$childInstance->useVarA(); // should echo 'dojo'
$parentInstance->setVarA(); // should set $varA to 'something grand'
$changedVarA = $parentInstance->getVarA(); // should set $changedVarA variable to 'something grand'
$childInstance->useVarA(); // should echo 'something grand' but fails to do so...how can I do this?
If you have either a private or a protected variable (member) in the parent then you can access it simply like this from you child class:
$this->varA = ‘something’;
There reason why your child method does not reflect the change, is that child and parent are two different objects in separate memory space. If you want them to share a value you could make it static.
You don’t need to declare it public.
class Parent {
private $varA;
protected $varB;
public $varC;
protected static $varD;
public function getD() {
return self::$varD;
}
public function setD($value) {
self::$varD = $value;
}
}
class Child extends Parent {
public function getA() {
return $this->varA;
}
public function getB() {
return $this->varB;
}
public function getC() {
return $this->varC;
}
}
$child = new Child();
$child->getA(); // Will not work since $varA is private to Parent
$child->getB(); // Works fine because $varB is accessible by Parent and subclasses
$child->getC(); // Works fine but ...
$child->varC; // .. will also work.
$child->getD(); // Will work and reflect any changes to the parent or child.
If you don’t want all instance of the parent class to share values. You could pass on the parent or child to either new instance and through and update the values of all the related objects accordingly.
$parent->addChild(new Child());
And in the set method:
$this->varA = $value;
foreach ($this->children as $child) {
$child->setVarA($value);
}
Hopes this helps.
What will happen if I create a class with a static property and create two instances of it?
Will the static property be shared between both instances and not be duplicated?
Yes, that is the definition of a static property.
Static properties belong to the class, not instances of the class.
class SomeClass {
private static $instanceCount = 0;
function __construct() {
self::$instanceCount++;
//do other stuff.
}
function instanceCount() {
return self::$instanceCount;
}
}
$one = new SomeClass();
echo $one->instanceCount(); //1
$two = new SomeClass();
echo $one->instanceCount(); //2
echo $two->instanceCount(); //2
is there a way to traverse an object to get the parent object data?
With "parent object" I don't mean the parent class, but literally object.
Here an example, in a javascripty world :-) :
$parent->test = "hello world!";
$parent->child = new B();
It would be great If I could access all the data from parent in the child object:
class B{
//I know this doesn't exists, but it's what I wanted do do
function B(){
$this->parent = $this->parent();
echo $this->parent->test; //it would ouput "hello world"
}
}
For now my solution is to pass the parent object to the child (as a reference) or to make the parent global.
Do you have any better solution?
Thanks!
There is no way to invoke
$parent->test = "hello world!";
$parent->child = new B();
and automatically have a reference to $parent in B.
Generally, there is four ways to structure your classes:
1. Aggregate the parent object via Injection, e.g.
class B
{
private $parent;
public function __construct($parent)
{
$this->parent = $parent;
}
public function setParent($parent)
{
$this->parent = $parent;
}
public function accessParent()
{
$this->parent->someMethodInParent();
}
}
Use constructor injection when the object has to have a parent when it's created. This is a has-a relationship and it creates a very loose coupling. There is no hardcoded dependencies in B, so you can easily swap out the Parent instance, for instance with a Mock when UnitTesting. Using Dependency Injection will make your code more maintainable.
In your UseCase, you'd pass $parent to B when creating B:
$parent->child = new B($parent);
2. Use Composition
class B
{
private $parent;
public function __construct()
{
$this->parent = new Parent;
}
public function accessParent()
{
$this->parent->someMethodInParent();
}
}
This is also a has-a relationship, but couples the Parent class to B. It's also not an existing Parent instance, but a new instance. From the wording I find it somewhat odd to have a parent created by the child. Use this, when dependency is a class that is not considered to exist outside of the root class, but is part of the whole thing it represents.
For your UseCase, there is no way of doing $parent->child = new B(); and know what parent is when using this approach, unless $parent is a Singleton. If so, you could get the Singleton instance, e.g. Parent::getInstance() to achieve what you want, but note that Singletons are not everyone's favorite pattern, e.g. hard to test.
3. Use Inheritance
class B extends Parent
{
public function accessParent()
{
$this->someMethodInParent();
}
}
This way you create an is-a relationship. All public and protected methods and properties from the Parent class, (but not of a specific instance) will be available in B and you can access them via the $this keyword of the B instance.
For your UseCase, this approach is not working, as you don't have to have an instance of Parent at all, but B would encapsulate everything of Parent when it's created
$b = new B;
4. Use global keyword
class B extends Parent
{
private $parent;
public function __construct()
{
global $parent;
$this->parent = $parent;
}
public function accessParent()
{
$this->parent->someMethodInParent();
}
}
The global keyword imports global variables into the current scope. In general, you should avoid using the global keyword in an OO context, but use one of the other three methods above, preferably the first one. While it's a language feature, it's frowned upon - although it is the next closest thing to the first one, e.g.
$parent->child = new B();
Anyway, hope that helps.
Passing the parent to the child is the better solution. Though it's a somewhat undesirable symbiotic relationship.
Should B() have any knowledge of the object it's an attribute of? More than likely not. These are only loosely related via composition.
Why does B() need to be an attribute of it's parent? Do you need to have this implementation in B() or should it be part of the parent?
Maybe it can be useful in some case: it doesn't bring parent object to ChildClass very early in constructor, but a one step later. It plays with ability to intercept non-existing method:
class ParentClass
{
const CHILD_PROPERTY_NAME = 'child';
public $data = 'Some data';
public function
__set($property_name, $property_value)
{
if ($property_name == self::CHILD_PROPERTY_NAME)
{
$property_value->set_parent_object($this);
}
}
}
class ChildClass
{
private $parent_object = null;
public function
set_parent_object($object)
{
$this->parent_object = $object;
echo $this->parent_object->data;
}
}
$p = new ParentClass();
$p->child = new ChildClass();
This will output Some data
I'm pretty sure, that PHP does not have something like that.
Your solution of passing the parent-object to the child is the best solution, I think. You should consider to set your Parent-property only in the constructor of the child to prevent multiple parents from having the same child.
No.
You can access variables from the superclass using $this:
<?php
class A {
public function __construct()
{
$this->foo = 'hello';
}
}
class B extends A {
public function printFoo()
{
echo $this->foo;
}
}
$b = new B();
$b->printFoo();
?>
You can create collections of object children when you create the children. you create it trough the parent this way they cannot reference each other but you can access both parents and children trough the parent and trough the children...
class ChildObject
{
public $name;
}
class ParentObject
{
public $children = array();
public function new_child($text = 'my name is data')
{
$child = new ChildObject; // create a new child
$child->name = $text; // assign the name
$this->children[] = $child; // store it as part of this object
return $child; // return the new instance of Child
}
public function print_everything ()
{
foreach($this->children as $child) {
echo $child->name;
}
}
}
$parent = new ParentObject;
$child1 = $parent->new_child(); // this is a ChildObject not a ParentObject
$child2 = $parent->new_child('i am not data');
echo $child1->name; // 'my name is data'
echo $child2->name; // 'i am not data'
$child1->name = 'something else';
echo $child1->name; // 'something else'
$parent->print_everything(); // 'something else' and 'i am not data'
Therefore if you want to access a parent method or property, you should put that in the parent and not in the child. Remember that the parent is also an "instance" of its own class.