The extension idea is interesting! I hadn't thought of that. Autoloading
might be a PITA with that, I'm trying to think of how you would manage that?

On the subject of "mistaken typing" or implicit interfaces being met by
classes that don't actually do the desired behavior, I think you're right
it's a risk, my counterargument is typescript and golang both have implicit
interfaces in some form (well typescript calls them structural typing), but
I don't think in either language I've ever really run into a case where
that risk becomes a reality. I'm hesitant to declare this because I'm not
sure this is the best way to frame this from a PR perspective, but in many
respects this proposal is viewable as a syntax shortcut to duck typing,
which is already pretty common across PHP. While there are definitely
drawbacks to duck typing, it's still a very useful tool IMO (and becomes
very cumbersome if you need to duck type a larger set of functions).

On Fri, Nov 7, 2025 at 9:51 AM John Bafford <[email protected]> wrote:

> Hi Spencer,
>
> > On Nov 7, 2025, at 12:05, Spencer Malone <[email protected]>
> wrote:
> >
> > Hey all! Long time browser, first time emailer. I wanted to start a
> pre-RFC discussion on the proposal of opt-in implicit interfaces /
> structural typing / "golang style interfaces".
> >
> > I have an early mostly working POC at
> https://github.com/php/php-src/compare/master...SpencerMalone:php-src:implicit,
> and was curious if this was an idea that could get any traction as an RFC?
> >
> > For those who don't want to open the link, it's essentially:
> >
> > ```
> > implicit interface Drawable {
> >     public function draw(): void;
> > }
> >
> > class Circle {
> >     public function draw(): void {
> >     }
> > }
> >
> > assert((new Circle()) instanceof Drawable); // This would be true
> > ```
> >
> > There is some previous art around here in the form of...
> >
> > https://wiki.php.net/rfc/protocol_type_hinting - I couldn't find any
> discussion on this other than reading that the author withdrew all their
> RFCs for unrelated reasons I think? Some of the core ideas here I think are
> still relevant, although in my implementation I chose to use syntax that
> adds a keyword onto the interface rather than at the call sites because I
> wanted to provide the ability for interface definers to keep their
> interfaces as explicit if they wanted, as well as... Well honestly, adding
> angle brackets around objects feels like a syntax misstep since that
> pattern is very associated with generics in my mind. I could be convinced
> of this though if that's the syntax people prefer.
> >
> > https://externals.io/message/115554#115603 - Convinced me that others
> may want this as well, although again that proposed syntax ended up
> stepping on the toes of attributes. I do think this does a good job of
> explaining _why_ I want this.
> >
> > - Spencer
>
>
> I think this is an interesting idea, but personally, I would prefer to see
> classes always explicitly declare their interfaces. An interface is a
> contract, and implementing the interface is agreeing to conform to the
> contract. Just because a class has the shape of an interface doesn't mean
> it follows the contract. implicit would probably be most useful for very
> simple interfaces, but those are exactly the kind of interfaces that could
> be misinterpreted. For example, this poorly designed class:
>
> ```
> class DeckOfCards {
>         public ?Card $mostRecentlyDrawnCard;
>         public function draw() : void { ... }
> }
> ```
>
> should not be instanceof the Drawable interface, because it doesn't
> conform to the contract, even though it structurally matches.
>
> Perhaps slightly less torturously,
>
> ```
> class Canvas {
>         public array $contents; //list<Drawable>
>         private CanvasInternalRepresentation $internalRepresentation
>         public function draw() : void { ... update the canvas's internal
> representation ... }
>         public function data($imageType) : string { .. } // return binary
> blob of $imageType data from the internal representation
> }
> ```
>
> This Canvas takes a list of Drawables and uses a draw() method to update
> its internal representation. But it itself is not Drawable (let's say,
> because Canvas can't be nested for whatever reason).
>
>
> In real code, there's probably a lot of things that structurally would
> conform to some sort of simple Cache/Cacheable or Request/Response
> interface but for reasons wouldn't obey whatever implied contract those
> interfaces would demand.
>
>
> In my opinion, a better solution would be to allow for extensions that
> allow declaring interface conformances. e.g.
>
> ```
> extension Circle implements Drawable {
>         // We have now explicitly declared that Circle is a Drawable and
> conforms to its contract.
>         // This extension body is empty because Circle already has a
> conforming draw method,
>         // but if it didn't, we could add one here and it would be treated
> as part of the Circle class.
> }
> ```
>
> Of course, this would be a much more involved proposal than implicit
> interfaces, which does have elegance in its simplicity.
>
> -John
>
>

Reply via email to