# Dealing with Generalization

> Techniques that move members up and down class hierarchies, create or collapse hierarchies, and swap inheritance for delegation.

- kind: category
- category: refactoring
- canonical: https://aipatterns.dev/refactoring/techniques/dealing-with-generalization
- inspired-by: https://refactoring.guru/refactoring/techniques/dealing-with-generalization

## What these techniques solve

Inheritance hierarchies drift. Sibling classes copy the same method, a base class carries fields only one subclass uses, a subclass inherits a contract it can't honor, or a hierarchy has outlived the variation that justified it. These techniques reshape hierarchies, and replace inheritance with composition when the "is-a" relationship no longer holds.

**Put shared behavior at the lowest level that all of its users share, and prefer delegation whenever a subclass would ignore part of what it inherits.**

## Members

- [Pull Up Field](https://aipatterns.dev/refactoring/techniques/pull-up-field.md): move a field that all subclasses declare into the superclass.
- [Pull Up Method](https://aipatterns.dev/refactoring/techniques/pull-up-method.md): move identical methods from subclasses into the superclass.
- [Pull Up Constructor Body](https://aipatterns.dev/refactoring/techniques/pull-up-constructor-body.md): move shared constructor logic into a superclass constructor.
- [Push Down Method](https://aipatterns.dev/refactoring/techniques/push-down-method.md): move a superclass method used by only some subclasses into those subclasses.
- [Push Down Field](https://aipatterns.dev/refactoring/techniques/push-down-field.md): move a superclass field used by only some subclasses into those subclasses.
- [Extract Subclass](https://aipatterns.dev/refactoring/techniques/extract-subclass.md): move features used only in some instances into a new subclass.
- [Extract Superclass](https://aipatterns.dev/refactoring/techniques/extract-superclass.md): create a shared parent for two classes with common fields and methods.
- [Extract Interface](https://aipatterns.dev/refactoring/techniques/extract-interface.md): declare the subset of methods that several clients rely on as an interface.
- [Collapse Hierarchy](https://aipatterns.dev/refactoring/techniques/collapse-hierarchy.md): merge a subclass and superclass that are no longer different enough to keep apart.
- [Form Template Method](https://aipatterns.dev/refactoring/techniques/form-template-method.md): move a shared algorithm skeleton up and leave only the differing steps in subclasses.
- [Replace Inheritance with Delegation](https://aipatterns.dev/refactoring/techniques/replace-inheritance-with-delegation.md): hold the former superclass in a field and forward the calls you need.
- [Replace Delegation with Inheritance](https://aipatterns.dev/refactoring/techniques/replace-delegation-with-inheritance.md): subclass the delegate when a class forwards nearly its whole interface.

## How to choose within this category

- **Siblings duplicate members:** pull them up with [Pull Up Field](https://aipatterns.dev/refactoring/techniques/pull-up-field.md), [Pull Up Method](https://aipatterns.dev/refactoring/techniques/pull-up-method.md) and [Pull Up Constructor Body](https://aipatterns.dev/refactoring/techniques/pull-up-constructor-body.md). If the methods are similar but not identical, use [Form Template Method](https://aipatterns.dev/refactoring/techniques/form-template-method.md), or pass the differing step as a function.
- **The base class holds things only some subclasses use:** [Push Down Method](https://aipatterns.dev/refactoring/techniques/push-down-method.md) and [Push Down Field](https://aipatterns.dev/refactoring/techniques/push-down-field.md).
- **Two unrelated classes share behavior:** consider [Extract Superclass](https://aipatterns.dev/refactoring/techniques/extract-superclass.md) only if one really is a kind of the other. Otherwise extract a shared helper class and delegate to it. If clients need only a shared role, [Extract Interface](https://aipatterns.dev/refactoring/techniques/extract-interface.md). In Go, TypeScript and Python (with `Protocol`), structural typing means the interface can live with the client, and the classes don't need to declare it.
- **Some instances use features others don't:** [Extract Subclass](https://aipatterns.dev/refactoring/techniques/extract-subclass.md) if the variation is fixed at creation. If it changes at runtime, use [Replace Type Code with State/Strategy](https://aipatterns.dev/refactoring/techniques/replace-type-code-with-state-strategy.md) instead.
- **A subclass adds nothing meaningful:** [Collapse Hierarchy](https://aipatterns.dev/refactoring/techniques/collapse-hierarchy.md).
- **A subclass uses a small part of its parent or overrides methods to throw:** [Replace Inheritance with Delegation](https://aipatterns.dev/refactoring/techniques/replace-inheritance-with-delegation.md). This is the usual fix for [Refused Bequest](https://aipatterns.dev/refactoring/smells/refused-bequest.md).
- **A class forwards almost every method of a delegate it truly is a kind of:** [Replace Delegation with Inheritance](https://aipatterns.dev/refactoring/techniques/replace-delegation-with-inheritance.md). Check that the full inherited contract is acceptable first; when in doubt, keep delegation.

Go has no inheritance, so only the interface and delegation techniques apply there. Moving members along a hierarchy can change which override runs, so run the tests for every subclass after each move.
