I ran into this today with PHP (7.1 and 7.2 at least) with the following code:
namespace PlaceHolderX\Tests\PHPUnit\Unit;
use PHPUnit\Framework\TestCase;
final class BreakingClassesTest extends TestCase
{
public function testBreak(): void
{
$tester = new SomeClassA();
$tester->test();
$this->assertNull($tester->get());
}
}
interface InterfaceA {
public function test(string $testString): void;
}
class SomeClassA implements InterfaceA
{
/** @var null|string */
private $testString;
public function test(string $testString = null): void
{
$this->testString = $testString;
}
public function get(): ?string
{
return $this->testString;
}
}
So I have an interface (InterfaceA) that has a method that requires a string. This argument is not nullable, cause if I wanted that I would have specified it as:
public function test(?string $testString): void;
But in the implementation class (SomeClassA) I can override the argument definition with a default value of null which results in a behavior I didn't intend with my interface.
So my main question is: Why is this possible? Of course, we will need to check this in code reviews, but it is something that is easy to miss.
I tried searching what causes this behavior but was not able to find an explanation. Maybe my search criteria are off.