Skip to content

Adding a public method on a non-final class is to be considered a BC break #111

Open
@Ocramius

Description

@Ocramius

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.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions