Req #79720 [Sus]: Nested classes like in Java
Edit report at https://bugs.php.net/bug.php?id=79720&edit=1
ID: 79720
User updated by: 6562680 at gmail dot com
Reported by: 6562680 at gmail dot com
Summary: Nested classes like in Java
Status: Suspended
Type: Feature/Change Request
Package: Class/Object related
Operating System: Win10
PHP Version: 7.3.19
Block user comment: N
Private report: N
New Comment:
If we speaking about javascript where we have internal dependency injector - we could say about oop
principles.
oop has a point: object has state and behavior. if we need to change the object from the code - we
implement more methods to change. if methods are public - anybody could use internal objects public
methods.
I just little disappointed about "solid" principles with PHP - where we need to create
tonns of public methods, that of course, could be used outside the library and possible create
problems.
to inject dependencies we have to create factory/builder and pass container as a dependency in this
builder. Then we could create object and even then we need public methods or bound callbacks to fill
protected properties.
There are breaking incapsulation. First we declare property protected, then we create public methods
- same as we declare property "public". Because we need to separate opportunity of
injection/creating in different class, opportunity to control values - in second class, opportunity
to manage control values - in third class.
Otherwise we have mega-class with tonns of methods. We can separate it to traits simulating
multiple-extends, and for my points - there is something wrong in oop principles implementation.
Maybe oop was created for multiple extends, that causes many hardcoded objects and makes future
changes harder or impossible, especially if we talk about complete composer library, that cannot be
changed, and only decorated or replaced.
Change-ability has strong dependency from injector with interface-bound stuff. Otherwise you cannot
remove the module. In same time passing arguments to protected properties requires constructor (used
for dependencies), public methods - could be used by client where i didnt expect that, or bound
callbacks - that looks like oop-functional combination.
For example - you want to store messages in collection, and create class "inspection" that
do some job, and then fill this collection
class InspectionBuilder
{
protected $container;
public function __construct(PsrContainerInterface $container)
{
$this->container = $container;
}
// hello Java constructor overload
// but you right, if create constructor overloading it wouldn't help anything
// because class to create himself should contain DI as dependency
// there we could create Singletons and start to shit-coding with statics instead of interfaces,
because of PHP nature so
// We'll get a lock where we need self to build self. So builder - its the right way.
public function newInspectionFromSomething()
{
// damn, constructor requires arguments and couldn't be created
// return $this->container->get(Inspection::class);
// so we create own interface with method make()
$messagesCollection = $this->container->get(MessagesCollection::class);
$inspection = $this->container->make(Inspection::class, $someRequiredData = [123]);
$inspection->setMessagesCollection($messagesCollection);
// finally we have inspection...
return $inspection;
}
}
Class Inspection
{
protected MessagesCollection $messagesCollection;
protected mixed $someRequiredData;
public function __construct(array $someRequiredData)
{
// now we can new Inspection($data), but we still havent dependencies then
// hmm, make __construct(MessagesCollection $collection, $someRequiredData)
// but really it will be needed only when we start work with messages
// hmm, possible we have to create setMessagesCollection() method
$this->someRequiredData = $someRequiredData;
}
public function setMessagesCollection(MessagesCollection $messagesCollection)
{
$this->messagesCollection = $messagesCollection;
}
}
Class MessagesCollection
{
protected array $messages;
}
```
Next question is - how to add messages into this protected collection?
Create getter for collection? End-user will modify it and then forget where he did that.
So there should be possibility to work with single this outside functional way.
You know, alternative is to implement all of the methods by inspection, validation, message
compilation and building inside one Inspection class
First of all class becomes mega-size. Second - will break dependency-inversion where we can replace
custom behavior adding dependency by existing interface.
Something wents wrong in "oop implementation";
Functional programming provides import/export like ours "require/return" but then
autoloader wont work. Again the deadlock.
Java added nested classes and { get,set } syntax to reduce class size, makes it easier to read and
manage.
We should code on PHP style using functional style to make things, because of RFC denied. Should
think about it.
Classes should looks like:
```
Class A
{}
return [ 'a' => new A ];
```
and combine runtime/declaration in one file.
Previous Comments:
------------------------------------------------------------------------
[2020-06-21 20:00:23] requinix@php.net
*I* think there are already well-established OOP principles that make child classes irrelevant.
But regardless of what I think, a significant change like this requires the RFC process.
https://wiki.php.net/rfc/howto
But note that you're not the first to propose this:
A few years ago there was an RFC about nested classes. It was not completed.
https://wiki.php.net/rfc/nested_classes
The related concept of friend classes was submitted a bit more recently and declined.
https://wiki.php.net/rfc/friend-classes
------------------------------------------------------------------------
[2020-06-21 16:34:26] 6562680 at gmail dot com
Description:
------------
Am using \Closure with bind() to pass protected variables into instances from factory.
As i remember in Java we can define sharing this context to child classes.
Why it was removed?
```
Class A
{
public function newChildA()
{
$a = new ChildA;
$a->value = 123;
}
Class ChildA
{
protected $value;
}
}
```
Otherwise we should add setters, and somebody of course use it directly in his code.
Its about "readonly" property, not just "protected".
Main problem is "no internal dependency injector", we can pass attributes via
__construct... What if dependencies? We still need to create builder that should pass parameters to
constructor with autowired dependencies, and then we lost possibility to create object via
"new" operator, otherwise we should add container/di into each class as dependency.
Then we should remember base class dependency when extending and that stuff.
How do you think?
Test script:
---------------
Class A
{
public function newChildA($value)
{
$func = function ($value) {
$this->value = $value;
};
$a = new ChildA;
$func->call($a, 123);
}
}
Class ChildA
{
protected $value;
}
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=79720&edit=1
Thread (3 messages)