Polymorphism flows from abstractions. Once you define an interface like
Vehicle, each implementation can provide its own behavior. That way, callers
call methods on an interface, and the actual concrete type knows how to handle
itself.
Compare:
public enum SpotSize { Regular, Motorcycle, Large }
public class ParkingLot
{
public bool ParkVehicle(Vehicle vehicle)
{
var vehicleSize = vehicle.Type switch {
"car" => SpotSize.Regular,
"motorcycle" => SpotSize.Motorcycle,
"truck" => SpotSize.Large
};
var spot = FindAvailableSpotBySize(vehicleSize);
if (spot is null)
return false;
spot.Occupy(vehicle);
return true;
}
}
… to:
public enum SpotSize { Regular, Motorcycle, Large }
public abstract record IVehicle(SpotSize SpotSize);
public record Car() : IVehicle(SpotSize.Regular);
public record Motorcycle() : IVehicle(SpotSize.Motorcycle);
public record Truck() : IVehicle(SpotSize.Large);
public class ParkingLot
{
public bool ParkVehicle(IVehicle vehicle)
{
var spot = FindAvailableSpotBySize(vehicle.SpotSize);
if (spot is null)
return false;
spot.Occupy(vehicle);
return true;
}
}
Use polymorphism when behavior varies by type. Typical symptoms include writing type checks or switch statements on an enum.
While polymorphism affords flexibility and extensibility, highly polymoprhic code can be difficult to trace and debug. Match your code base’s tolerance for polymorphism.
- OOP Concepts | Hello Interview Low Level Design. www.hellointerview.com . Accessed Sep 14, 2026.
There is a second level to this. Polymorphism based on interfaces without any inheritance is cognitively lighter than inheritance mixed in. With inheritance, there’s a worry about what you see in the code is not what happens at runtime because someone overrides it (or removed the extension point).