Introduction:
Nested classes relate to other classes a little differently than to outer classes. Take Java as an example:
Non-static nested classes have access to other members of the enclosing class, even if they are declared private. In addition, non-static nested classes require an instance of the parent class to instantiate.
OuterClass outerObj = new OuterClass(arguments); outerObj.InnerClass innerObj = outerObj.new InnerClass(arguments);
There are several good reasons to use them:
- This is a way to logically group classes that are used in only one place.
If a class is useful only for one other class, then it is logical to link and insert it into this class and maintain them together.
- It increases encapsulation.
Consider two top-level classes: A and B, where B requires access to members of A, which would otherwise be declared private. By hiding class B in class A, members of A can be declared private and B can access them. In addition, B himself may be hidden from the outside world.
- Nested classes can lead to more readable and maintainable code.
A nested class usually refers to this parent class and together forms a "package"
In php
You may have similar behavior in PHP without nested classes.
If all you want to achieve is structure / organization, since Package.OuterClass.InnerClass, PHP namespaces might be sufficient. You can even declare more than one namespace in a single file (although this may not be desirable due to standard startup functions).
namespace; class OuterClass {} namespace OuterClass; class InnerClass {}
If you want to imitate other characteristics, such as the visibility of elements, a little more effort is required.
Class definition package
namespace { class Package { protected function __construct() {} public function __call($method, $args) {
Use case
namespace Package { class MyParent extends \Package { public $publicChild; protected $protectedChild; public function __construct() { //instantiate public child inside parent $this->publicChild = new \Package\MyParent\PublicChild(); //instantiate protected child inside parent $this->protectedChild = new \Package\MyParent\ProtectedChild(); } public function test() { echo "Call from parent -> "; $this->publicChild->protectedMethod(); $this->protectedChild->protectedMethod(); echo "<br>Siblings<br>"; $this->publicChild->callSibling($this->protectedChild); } } } namespace Package\MyParent { class PublicChild extends \Package { //Makes the constructor public, hence callable from outside public function __construct() {} protected function protectedMethod() { echo "I'm ".get_class($this)." protected method<br>"; } protected function callSibling($sibling) { echo "Call from " . get_class($this) . " -> "; $sibling->protectedMethod(); } } class ProtectedChild extends \Package { protected function protectedMethod() { echo "I'm ".get_class($this)." protected method<br>"; } protected function callSibling($sibling) { echo "Call from " . get_class($this) . " -> "; $sibling->protectedMethod(); } } }
Testing
$parent = new Package\MyParent(); $parent->test(); $pubChild = new Package\MyParent\PublicChild();
Output:
Call from parent -> I'm Package protected method I'm Package protected method Siblings Call from Package -> I'm Package protected method Fatal error: Call to protected Package::__construct() from invalid context
Note:
I really don't think trying to emulate innerClasses in PHP is such a good idea. I think the code is less clean and readable. In addition, there are probably other ways to achieve similar results using a well-established template such as the Observer template, Decorator ou COmposition. Sometimes even simple inheritance is enough.