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.