# Object-Orientation Abusers

> Smells where object-oriented features are missing or misapplied, such as type switches, half-used fields and inheritance that does not fit.

- kind: category
- category: refactoring
- aliases: OO Abusers
- canonical: https://aipatterns.dev/refactoring/smells/oo-abusers
- inspired-by: https://refactoring.guru/refactoring/smells/oo-abusers

## What these smells share

These smells come from using classes without using what classes offer. Code branches on a type tag instead of letting each type answer for itself. Fields exist for only one code path. Subclasses inherit methods they refuse to support. Two classes do the same job behind different method names.

The cost is fragility. Adding a variant means finding every switch. Calling a method on a subclass may throw. Swapping one implementation for another means rewriting callers.

## Members

- [Switch Statements](https://aipatterns.dev/refactoring/smells/switch-statements.md): the same `switch` or `if/else` chain over a type code is repeated in several places.
- [Temporary Field](https://aipatterns.dev/refactoring/smells/temporary-field.md): a field is set and read only during one operation and is empty or meaningless the rest of the time.
- [Refused Bequest](https://aipatterns.dev/refactoring/smells/refused-bequest.md): a subclass ignores, overrides with no-ops, or throws on methods it inherits.
- [Alternative Classes with Different Interfaces](https://aipatterns.dev/refactoring/smells/alternative-classes-with-different-interfaces.md): two classes do the same thing but expose different method names and signatures.

## How to choose within this category

- If the problem is a conditional on a kind or status, it is [Switch Statements](https://aipatterns.dev/refactoring/smells/switch-statements.md). One switch is fine; the same switch in three places is the smell.
- If the problem is a field that is often `null` or unset, it is [Temporary Field](https://aipatterns.dev/refactoring/smells/temporary-field.md). Look for the one method that uses it.
- If the problem is inheritance that does not hold, such as overridden methods that throw `NotSupported`, it is [Refused Bequest](https://aipatterns.dev/refactoring/smells/refused-bequest.md).
- If the problem is two types that could be swapped but cannot because their APIs differ, it is [Alternative Classes with Different Interfaces](https://aipatterns.dev/refactoring/smells/alternative-classes-with-different-interfaces.md).

## Typical treatments

- [Replace Conditional with Polymorphism](https://aipatterns.dev/refactoring/techniques/replace-conditional-with-polymorphism.md) and [Replace Type Code with State/Strategy](https://aipatterns.dev/refactoring/techniques/replace-type-code-with-state-strategy.md) for type switches.
- [Extract Class](https://aipatterns.dev/refactoring/techniques/extract-class.md) and [Introduce Null Object](https://aipatterns.dev/refactoring/techniques/introduce-null-object.md) for temporary fields.
- [Replace Inheritance with Delegation](https://aipatterns.dev/refactoring/techniques/replace-inheritance-with-delegation.md) and [Push Down Method](https://aipatterns.dev/refactoring/techniques/push-down-method.md) for refused bequests.
- [Rename Method](https://aipatterns.dev/refactoring/techniques/rename-method.md), [Extract Superclass](https://aipatterns.dev/refactoring/techniques/extract-superclass.md) and [Extract Interface](https://aipatterns.dev/refactoring/techniques/extract-interface.md) for mismatched interfaces.

## For agents

- Polymorphism is not always the answer. In languages with sum types and exhaustive pattern matching (TypeScript discriminated unions, Rust, Kotlin sealed classes, Swift enums), one exhaustive `switch` checked by the compiler is often clearer than a class hierarchy.
- Prefer composition when fixing inheritance problems. Do not add a deeper hierarchy to fix a shallow one.
