Skip to content

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

Open
@Ocramius

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions