Search code examples
ooplanguage-agnostic

Is it discouraged to down-cast a returned instance to gain functionality that is not exposed via the returned class type?


This is the basic scenario: A method returns a class of type A, but after looking at the internal workings of the code it is found safe to assume that it actually returns B (a subclass of A). Is it then valid to do something like this? Or would you highly discourage it because it is accessing protected data (at least):

Assume that you do not maintain this code that implements the method as well. I.e, your software could ship with a different implementation of this (well established) method.

A returnedData = executeMethod();
if(returnedData instanceof B)
{
    ((B)returnedData).someFunctionNotExposedThroughAIsItProtected();
    //Use it as B, safe but non OOP and accessing protected functionality?
}else
    writeAFallBackOfSomeSort();

Solution

  • The key point is the if(returnedData instanceof B): if such a statement exist, it is proven that the returned object is a B (which in turn also includes A), so using B public method is safe.

    In pure OOP sense this is not "elegant", but it is often the pragmatic way to go. Think a while: a Dog is an Animal, but is unlikely that Animal has a do-nothing bark method, otherwise -for completeness- it must have all methods for all possible animals may have, thus making Animal a sort of "God Object" (a well known anti-pattern).

    It is more pragmatic once you've got an Animal, ask it to bark only after you recognized it is a Dog. You can have then more Dog subclasses (representing different dog races) barking differently, but bark belongs to Dogs, not Animal in general.

    The problem now becomes: is it correct to suppose an Animal could be a Dog? If you can check it, why not!

    Use OOP as a technique where convenient, not as a religion to serve.

    Consider also that the answer can change depending on the language used and on what feature it has around objects and the way it define what a "object" is. Where no runtime dispatch exist (or where runtime dispatch is single and you need multiple) this can be even a well established method.