01/09/2017 - PHP
Any method that takes class X as an argument must be able to work with any sub classes of X. In short terms, a subclass should be able override the parent class' methods without breaking functionality. Another way of describing it is, an object with a specific interface can be replaced by a different object with same interface without breaking the application's original behaviour.
# VIOLATION
interface SportsInterface
{
public function pass(string $ball);
public function tackle(string $opponent);
}
class Footballer implements SportsInterface
{
public function pass(string $ball)
{
// Passing the $ball
}
public function tackle(string $opponent)
{
// Tackling the $opponent
}
}
class English extends Footballer implements SportsInterface
{
public function pass(string $ball)
{
// I am able to pass the $ball
}
public function tackle(string $opponent)
{
// I am able to tackle the $opponent
}
}
class Spanish extends Footballer implements SportsInterface
{
public function pass(string $ball)
{
// I am able to pass the $ball
}
public function tackle(string $opponent)
{
throw new Exception('Sorry, I am too nice to tackle my opponents.');
}
}
In example above, we expect English
and Spanish
footballers to be able to pass
the ball and tackle opponents as Footballer
class dictates. However, the Spanish
footballer doesn't seem to be able to tackle
opponents. This is a violation because Footballer
class dictates the tackle
.
# VIOLATION
class Outputer
{
private $computer;
public function __construct(ComputerInterface $computer)
{
$this->computer = $computer;
}
public function output()
{
return implode(',', $this->computer->getData());
}
}
interface ComputerInterface
{
public function getData();
}
class Terminal implements ComputerInterface
{
protected $data;
public function __construct($data)
{
$this->data = $data;
}
public function getData()
{
return $this->data;
}
}
class Browser extends Terminal
{
public function __construct($data)
{
parent::__construct($data);
}
public function getData()
{
return json_encode($this->data);
}
}
# This would work
$terminal = new Terminal(['Hello', 'World']);
$outputer = new Outputer($terminal);
echo $outputer->output();
# This would fail
$browser = new Browser(['Hello', 'World']);
$outputer = new Outputer($browser);
echo $outputer->output();
This is another violation example. The reason why this is a violation is because the getData
method of Browser
subclass returns a JSON encoded string instead of an array like dictated in parent Terminal
class. When we inject:
Terminal
object into Outputer
class, the output is Hello,World
,Browser
object into Outputer
class, the output is PHP Warning: implode(): Invalid arguments passed in ......