php: property inheritance on nested class structure

php abstract class
inheritance in php w3schools
php class properties
php ::class
php interface
php trait
php anonymous class
php private class

It's not clear to me how class inheritance is implemented in php 5.4.7 (almost old! I know!). Consider this example:

Class ClassA {
    public $property = array();
    function __construct() {
        $this->property[] = "ClassA.construct";
    }
    public function SetA() {
        $this->property[] = "ClassA.Set";
    }
}

Class ClassB extends ClassA {
    function __construct() {
        $this->property[] = "ClassB.construct";
    }
    function SetB() {
        $this->property[] = "ClassB.Set";
    }
}

If I call in sequence

$classA = new ClassA();
$classA->SetA();
$classB = new ClassB();
$classB->SetB();
print_r($classB->property);

My expected behavior is to have...

Array
(
    [0] => ClassA.construct
    [1] => ClassA.Set
    [2] => ClassB.construct
    [3] => ClassB.Set
)

...but I obtain instead...

Array
(
    [0] => ClassB.construct
    [1] => ClassB.Set
)

So, what's wrong on my side? How can I add element from a Child to an array defined on Parent object?

In PHP, parent constructors aren't called automatically, to get your behaviour you need to do the following:

Class ClassB extends ClassA {
    function __construct() {
        parent::__construct();
        $this->property[] = "ClassB.construct";
    }
    function SetB() {
        $this->property[] = "ClassB.Set";
    }
}

And, at most, you'll get this

Array
(
    [0] => ClassA.construct
    [2] => ClassB.construct
    [3] => ClassB.Set
)

as SetA() is never invoked

When you invoked the sequence you described, $classA and $classB are two different instances, so you will never get what you expect.

To get what you want, you need to do this:

$classB = new ClassB();
$classB->SetB();
$classB->SetA();
print_r($classB->property);

Object Inheritance - Manual, This principle will affect the way many classes and objects relate to one another. then the parent class must be declared before the child class structure. Inheritance is a well-established programming principle, and PHP makes use of this principle in its object model. This principle will affect the way many classes and objects relate to one another. For example, when you extend a class, the subclass inherits all of the public and protected methods from the parent class.

You misunderstand how inheritance works in general: $classA is an instance of ClassA and has nothing to do with the instance $classB of ClassB you have generated.

An instance of ClassB inherits all public and protected properties and methods of ClassA but as long as you don't use them, you will not see them.

And all instances, whether from ClassA or from ClassB, are unrelated to each other, they only have the same "template" but each has its own property values.

Anonymous classes - Manual, Nesting an anonymous class within another class does not give it access to any private or protected methods or properties of that outer class. In order to use the  The BlackjackCard structure contains two nested enumeration types called Suit and Rank. In Blackjack, the Ace cards have a value of either one or eleven. This feature is represented by a structure called Values, which is nested within the Rank enumeration: struct BlackjackCard {. // nested Suit enumeration.

That's really simple: why did you expect the parent constructor to run if you forgot to call it in ClassB? According to https://3v4l.org/keJ2a, this has not changed since PHP 5.0.0 and still works the same in recent PHP 7 versions

Traits - Manual, File System Related Extensions · Human Language and Character Encoding Traits are a mechanism for code reuse in single inheritance languages such as PHP. An inherited method from a base class is overridden by the method inserted Prior to PHP 7.0, defining a property in a class with the same name as in a  For reflection, properties and events are hide-by-name-and-signature. If you have a property with both a get and a set accessor in the base class, but the derived class has only a get accessor, the derived class property hides the base class property, and you will not be able to access the setter on the base class.

If you want to get the expected result then you need to change the code as per the PHP oops concept this will not work as you want.

You Updated Code

Class ClassA {
    public $property = array();
    function __construct() {
        $this->property[] = "ClassA.construct";
        $this->SetA();
    }
    public function SetA() {
        $this->property[] = "ClassA.Set";
    }
}

Class ClassB extends ClassA {
    function __construct() {

        parent::__construct();//invoke parent constructor       
        $this->property[] = "ClassB.construct";
    }
    function SetB() {
        $this->property[] = "ClassB.Set";
    }
}


$classB = new ClassB();
$classB->SetB();
print_r($classB->property);

Expected result:

Array
(
    [0] => ClassA.construct
    [1] => ClassA.Set
    [2] => ClassB.construct
    [3] => ClassB.Set
)

When parent::__construct(); invokes then it maintains $property array variable for child class also.

Note: As we know OOPS concept, every object has a different instance.

Scope Resolution Operator (::) - Manual, As of PHP 5.3.0, it's possible to reference the class using a variable. parent and static are used to access properties or methods from inside the class definition. Although the nested class idiom is not a common-place idiom, nested classes do demonstrate on facet of the breadth and depth of changes in VB.NET that make it a first class language. A nested class is quite simply a class defined within a class. Technically, wherever you can use a nested class you could use a non-nested class; thus the reason for employing the nested class idiom is a semantic reason.

Class Constants - Manual, The default visibility of class constants is public. The value must be a constant expression, not (for example) a variable, a property, or a function call. It's also  Inheritance Basics (Visual Basic) 07/20/2015; 6 minutes to read +5; In this article. The Inherits statement is used to declare a new class, called a derived class, based on an existing class, known as a base class. Derived classes inherit, and can extend, the properties, methods, events, fields, and constants defined in the base class.

Inheritance, Use inherited objects just like you use regular Propel model objects: Class Table Inheritance uses one table per class in the inheritance structure ; each table  Hiding PHP Keeping Current Features HTTP authentication with PHP Cookies Sessions Dealing with XForms Handling file uploads Using remote files Connection handling Persistent Database Connections Safe Mode Command line usage Garbage Collection DTrace Dynamic Tracing Function Reference Affecting PHP's Behaviour Audio Formats Manipulation

Inheritance in Python Inner Class, Inheritance in Python Inner Class. A class is a user-defined blueprint or prototype from which objects are created. Classes provide a means of bundling data and  A class is a user-defined blueprint or prototype from which objects are created. Basically, a class combines the fields and methods (member function which defines actions) into a single unit. In C#, a user is allowed to define a class within another class. Such types of classes are known as nested class.

Comments
  • on other hands there's no possibility for classB to access to values of $property defined on classA. Isn't it?
  • @StefanoRadaelli Yes there is, if the property if public or protected or if there is a setter in ClassA to set a private property. However, the property is still specific for that instance of ClassB, it does not change anything in other objects of ClassA or ClassB.
  • Also you need to call SetA() somewhere in your class B instance to get [1] => ClassA.Set in your array.
  • That's clear. But in this case ClassA->SetA() method cannot be called upon certain condition. My goal is to (#1) instanciate ClassA with some values from __construct, (#2) then call main.php -> ClassA->SetA() if "a certain condition is true" and (#3) then to allow to ClassB to get all the values of $property already set from ClassA.
  • Yes, you are right but can not go against rules. Also, we can not merge two instances into a single one.