- 
                Notifications
    
You must be signed in to change notification settings  - Fork 61
 
Open
Labels
Description
Take following example:
class Counter
{
    private $count = 0;
    public function increment() : void {
        $this->count += 1;
    }
    public function count() : int {
        return $this->count;
    }
}
class LoggingCounter extends Counter
{
    private $logger;
    private $originalCounter;
    public function __construct(Logger $logger, Counter $originalCounter)
    {
         $this->logger = $logger;
         $this->originalCounter = $originalCounter;
    }
    public function increment() : void {
        $this->logger->log('increment');
        $this->originalCounter->increment();
    }
}If Counter is modified to add an increment2 method, LoggingCounter fails (this is partly described in my article "When to declare Classes Final" ).
class Counter
{
    private $count = 0;
    public function increment() : void {
        $this->count += 1;
    }
    public function increment2() : void {
        $this->count += 2;
    }
    public function count() : int {
        return $this->count;
    }
}Here's a test to show that:
class LoggingCounterTest extends TestCase
{
    public function incrementAndIncrement2() : void
    {
        $counter = new LoggingCounter($this->createMock(Logger::class), new Counter());
        
        $counter->increment();
        $counter->increment2();
        self::assertSame(3, $counter->count());
    }
}This is because decorators require an update for each parent class public API change. Therefore, we should mark any addition of methods to an open class as a BC break.
rpkamp and Slamdunk