# Refused Bequest

## Overview

Refused Bequest occurs when a subclass inherits from a parent but ignores or actively rejects much of what it receives. The subclass might leave inherited methods unused, or override them solely to throw exceptions. This is a strong signal that the inheritance relationship is wrong - the subclass is borrowing code rather than genuinely being a specialized version of the parent. The Liskov Substitution Principle is the clearest casualty: you cannot safely substitute the child where the parent is expected.

## Why It's a Problem

- **False "is-a" Relationship**: Inheritance should express a genuine conceptual specialization, not serve as a shortcut for code reuse
- **Developer Confusion**: The class hierarchy sends misleading signals about what each class represents and how it should be used
- **Artificial Coupling**: The subclass becomes dependent on a parent it has little real connection to
- **Broken Substitutability**: Subclasses that throw exceptions on inherited methods cannot be used interchangeably with the parent
- **Unpredictable Cascading**: Changes to the parent ripple into the subclass in unexpected ways

## Signs and Symptoms

- A subclass overrides parent methods only to throw exceptions or return dummy values
- The majority of inherited methods and properties go unused in the subclass
- Parent and child represent fundamentally different domain concepts
- Client code uses type checks or instanceof rather than trusting polymorphism
- Code reviewers question why the inheritance relationship exists

## Before/After

### Problem: Bird Hierarchy (Before)

```php
<?php

declare(strict_types=1);

abstract class Bird
{
    abstract public function fly(): void;
    abstract public function layEgg(): void;
}

class Sparrow extends Bird
{
    public function fly(): void
    {
        echo "Sparrow flying";
    }

    public function layEgg(): void
    {
        echo "Laying egg";
    }
}

class Penguin extends Bird
{
    public function fly(): void
    {
        throw new RuntimeException('Penguins cannot fly');
    }

    public function layEgg(): void
    {
        echo "Laying egg";
    }
}
```

### Solution: Extract to Interface (After)

```php
<?php

declare(strict_types=1);

interface Swimmer
{
    public function swim(): void;
}

interface Flyer
{
    public function fly(): void;
}

interface EggLayer
{
    public function layEgg(): void;
}

class Sparrow implements Flyer, EggLayer
{
    public function fly(): void
    {
        echo "Sparrow flying";
    }

    public function layEgg(): void
    {
        echo "Laying egg";
    }
}

class Penguin implements Swimmer, EggLayer
{
    public function swim(): void
    {
        echo "Penguin swimming";
    }

    public function layEgg(): void
    {
        echo "Laying egg";
    }
}
```

## Recommended Refactorings

### 1. Replace Inheritance with Composition (Delegation)
Use composition when classes share behavior but lack a genuine "is-a" relationship. Move shared code into helper classes.

```php
<?php

declare(strict_types=1);

readonly class DatabaseLogger
{
    public function __construct(
        private LogRepository $repository
    ) {}

    public function log(string $message): void
    {
        $this->repository->save($message);
    }
}

readonly class FileLogger
{
    public function __construct(
        private LogRepository $repository
    ) {}

    public function log(string $message): void
    {
        $this->repository->save($message);
    }
}
```

### 2. Extract a Proper Base Class
Identify what's genuinely shared and create a minimal parent class with only essential members.

```php
<?php

declare(strict_types=1);

abstract readonly class Logger
{
    public function __construct(
        protected string $level = 'INFO'
    ) {}

    abstract public function log(string $message): void;

    protected function format(string $message): string
    {
        return sprintf('[%s] %s', $this->level, $message);
    }
}

final class ConsoleLogger extends Logger
{
    public function log(string $message): void
    {
        echo $this->format($message);
    }
}
```

### 3. Use Enums for Type Safety
Replace inheritance hierarchies with enums when representing fixed sets of related values.

```php
<?php

declare(strict_types=1);

enum TransportMode
{
    case Air;
    case Land;
    case Sea;

    public function capabilities(): array
    {
        return match ($this) {
            self::Air => ['fly', 'land'],
            self::Land => ['drive', 'park'],
            self::Sea => ['swim', 'dock'],
        };
    }
}
```

## Exceptions

Refused Bequest is acceptable in these scenarios:

- **Deliberate interface compliance**: Using a base class for type-hinting while intentionally overriding methods (with clear documentation)
- **Legacy code**: Gradual refactoring of inherited systems where immediate changes aren't feasible
- **Template Method Pattern**: Abstract base class with some methods meant to be overridden while others are consistently used
- **Library design**: When a base class defines a contract but implementations vary significantly

## Related Smells

- **Parallel Inheritance Hierarchies**: Multiple inheritance chains that mirror each other's structure
- **Inappropriate Intimacy**: Classes that know too much about each other's implementation details
- **Large Class**: An overly broad parent class is a common root cause - the child only needs a fraction of what the parent offers
- **Lazy Class**: A subclass that contributes almost nothing beyond its parent
