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