Class Re-implementation Mechanism
| From: | someniatko | Date: | Tue, 21 Feb 2023 11:52:35 +0000 |
| Subject: | Class Re-implementation Mechanism | ||
| Groups: | php.internals | ||
| Request: | Send a blank email to internals+get-119584@lists.php.net to get a copy of this message | ||
Hi again, internals
My marathon of some crazy ideas continues :D, with less crazy one this time.
## Idea
Allow "reimplementing" the non-static public API (that is public
properties and methods, excluding constructor) of a class by other
classes like this:
```php
final class interface A {
public string $s;
public function __construct(string $s) { $this->s = $s; }
public static function fromInt(int $i): self { return new
self((string) $i); }
public function foo(): int { return 42; }
}
final class B implements A {
public string $s = 'hello';
public function foo(): int { return 69; }
}
function usesA(A $param): void {}
usesA(new B); // this works
```
## Explanation
Consider there is a class like this:
```php
final class Service {
public function __construct(private SomeDependency $dependency) {}
// ...
}
final class SomeDependency {
// ...
}
```
We want to write some tests for the Service class, but we don't want
to use a real SomeDependency instance
during tests. A common approach is to either extract an interface
(JUST to make it testable), or to drop the
final keyword and allow extending the class.
Both approaches have their flaws:
- extracting an interface unnecessarily complicates the system, where
only one "real" implementation of an interface is assumed.
- dropping the final keyword allows for the rabbit-hole of
inheritance abuse, like greatly described in this article:
https://front-line-php.com/object-oriented
I believe I came up with a better idea: what if we could leave both
benefits of prohibiting the inheritance abuse and also allow not to
clutter our namespace with excess entities like interfaces? I hereby
suggest to combine the responsibilities of a class and an interface
into one thing like that:
```php
final class interface C {}
final class D implements C {}
```
Now other classes can "implement" this class as well. Introduction of
the new syntax (class interface) also solves BC problem - if you
want to forbid your classes to be reimplemented whatsoever, you can
still stick to the final class syntax. Although it is also possible
to allow "reimplementing" ANY class, then new syntax is not needed -
but some library writers like Marco Pivetta could be sad about that I
suppose.
Soo..., what do you think? Could this be a valuable addition to the language?
Regards,
Illia / someniatko