safer casts, clearer if-else chain