Skip to content

Instantly share code, notes, and snippets.

@bdsl
Last active March 19, 2018 20:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bdsl/7f368a133670ed0612ce4e19150d5876 to your computer and use it in GitHub Desktop.
Save bdsl/7f368a133670ed0612ce4e19150d5876 to your computer and use it in GitHub Desktop.
Could there be an 'implementedBy' keyword?

I wonder if it would be practical to add an implementedBy keyword to PHP or other OO programming languages. I imagine it could help a lot with keeping application code decoupled from third party library code, and following the interface segregation principle.

For instance if I work at Acme and I want to use the Money PHP library, but not couple my code to it directly, I could write an interface with just the methods I need:

<?php
namespace Acme;

interface Money implementedBy \Money\Money
{
    public function greaterThan(Money $other);
    public function getAmount();
    public function multiply($multiplier, $roundingMode = self::ROUND_HALF_UP);
}

Then I'd write business logic code with type hints for Acme\Money instead of Money\Money:

<?php
namespace Acme

class RegularPayment
{
   /** @var Money */
   private $sum;

   /** @var \DateInterval */
   private $period;
   
   public function __construct(Money $sum, \DateInterval $period)
   {
       $this->sum = $sum;
       $this->period = $period;
    }

   public function getAnnualTotal() : Money
   {
     return $this->sum->multiply(365/$period->d);
   }
}

If I wanted to switch to a different implementation later I'd just have either arrange for it to explicitly implement Acme\Money, or add its name to the implementedBy statement.

Markku Sakkinen, Philippe Lahire and Ciprian-Bogdan Chirila proposed a similar idea for the Eiffel language, but I don't know if anything like it has been implemented in any language. Towards Fully-fledged Reverse Inheritance in Eiffel. 11th Symposium on Programming Languages and Software Tools (SPLST’09), Aug 2009, Tampère, Finland. pp.1-16, 2009.

Given that this keyword isn't currently available in PHP, the closest equivilent is probably:

<?php
namespace Acme

class Money extends \Money\Money implements Interfaces\Money
{
   // block intentionally left empty
}
<?php
namespace Acme\Interfaces;

interface Money
{
    public function greaterThan(Money $other);
    public function getAmount();
    public function multiply($multiplier, $roundingMode = self::ROUND_HALF_UP);
}

And then write the business logic code like RegularPayment to type hint against the \Acme\Interfaces\Money rather than either \Money\Money or \Acme\Money. This achieves almost the same ends of interface segregation and loose coupling as the hypothetical implementedBy keyword would, while probably being less confusing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment