What is your perspective on downcasting? Is it ALWAYS wrong, or are there cases where it is acceptable, or even preferable or desired?
Is there some good measure/guideline we can give that tells us when downcasting is "evil", and when it's "ok"/"good"?
(I know a similar question exists, but that question spins out from a concrete case. I'd like to have it answered from a general design perspective.)
Downcasting is not allowed without an explicit type cast. The reason for this restriction is that the is-a relationship is not, in most of the cases, symmetric. A derived class could add new data members, and the class member functions that used these data members wouldn't apply to the base class.
Upcasting is always safe and never fails. Downcasting can risk throwing a ClassCastException, so the instanceof operator is used to check type before casting.
Upcasting (Generalization or Widening) is casting to a parent type in simple words casting individual type to one common type is called upcasting while downcasting (specialization or narrowing) is casting to a child type or casting common type to individual type.
Upcasting is allowed in Java, however downcasting gives a compile error. The compile error can be removed by adding a cast but would anyway break at the runtime.
No, it's definitely not always wrong.
For example, suppose in C# you have an event handler - that gets given a sender
parameter, representing the originator of the event. Now you might hook up that event handler to several buttons, but you know they're always buttons. It's reasonable to cast sender
to Button
within that code.
That's just one example - there are plenty of others. Sometimes it's just a way around a slightly awkward API, other times it comes out of not being able to express the type within the normal type system cleanly. For example, you might have a Dictionary<Type, object>
appropriate encapsulated, with generic methods to add and retrieve values - where the value of an entry is of the type of the key. A cast is entirely natural here - you can see that it will always work, and it's giving more type safety to the rest of the system.
It's never an ideal solution and should be avoided wherever possible - unless the alternative would be worse. Sometimes, it cannot be avoided, e.g. pre-Generics Java's Standard API library had lots of classes (most prominently the collections) that required downcasting to be useful. And sometimes, changing the design to avoid the downcast would complicate it significantly, so that the downcast is the better solution.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With