On Tue, Feb 21, 2023 at 12:52 PM someniatko <somenia...@gmail.com> wrote:
>
> 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
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: https://www.php.net/unsub.php
>

This reminds me a lot of C#'s "extension methods" which are quite
useful. If PHP had something like that, you could do some really nice
things:

class BMock {
  public static function bar from A(): int { return 69; }
}

$a = new A(123);
echo $a->bar(); // output: 69

class BReal {
  public static function bar from A(): int { return $self->foo(); }
}

// error A::bar() already defined on BMock

where `from A` is syntax sugar for `public function bar(A $self) {}`
and trying `$a->bar()` is simply syntax sugar for `BMock::bar($a);`

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php

Reply via email to