So, I am super new to OOP and Java--specifically, just finishing up my first semester of it.
I understand interfaces are akin to contracts, and un...
For further actions, you may consider blocking this person and/or reporting abuse
There are only a few situations where I've explicit cast to an interface:
object
or a base class. That is, an implicit cast doesn't work in these situations.The idea of casting to an explicit interface just to limit the interface, used locally in a function, seems like an anti-pattern to me: the function is mixing multiple divergent purposes. If you have the full object then you can use it. If you're making generic code then put it in a function that takes only the interface.
I agree 100% it's an anti-pattern.
Casting to an interface allows you to pass/refer to objects with the same behavior.
For example, if you wanted to make a report from a bunch of forecasts you could write code like this:
Here you can see that we only need the
Forecastable
subset of these objects' functionality so we cast them to the interface.If you cast to
Forecastable
, then that object can only access the methods of the interface, you can't access other methods in theWeather
orStockMarket
class.Okay, that makes sense. But why would you want to do that?
One reason is that you want to ensure that no methods that aren't part of the contract are called on the object. If the interface represents a contract, yet you can call a method that isn't on the interface, in a sense, the contract has been broken!
I will say that it's somewhat odd to cast a type to accomplish this. Typically you would either instantiate an object of the interface type, for example:
Or, you make sure your methods accept only the contract, and not the implementation:
This way, even though the underlying type is a
MyContractImpl
, you won't be able to call methods on it that aren't a part ofMyContract
!You can do that for example to check whether some class implements an interface at runtime with a try catch block, if the cast fails then you can throw an error saying that the class should implement the interface, one example is to make a callback between Activity and Fragment in Android.
This would be a programming error and you shouldn't use the Exception mechanism to catch errors.
Every point of code should only see the minimum amount of stuff it needs to see. The less it sees, the less complexity it has to deal with and thus it itself will probably less complex.
This is not only trivially true for methods, where using the interface as a parameters also makes it a lot more generic, but even when designing interfaces: Implementing multiple smaller interfaces are preferable over big composite ones, because if your interfaces are big, the code sees a lot of stuff that it doesn't actually need. With multiple smaller interfaces, the code can work with the one that it actually needs and doesn't even see the other stuff. This is, I believe, called the interface segregation principle (see en.wikipedia.org/wiki/Interface_se...).
Where does this lead? It leads us to almost automatically casting to the interface. When we write something like this...
Weather weather = new Weather();
...we immediately ask ourselves: "Does the code that follows actually need the complete Weather? Or will all following code work fine with a Forecastable?" In the later case, we can immediately replace it with...
Forecastable forecastable = New Weather();
...since we know that we don't actually care that it's Weather. Of course, if we do care, we need to work with Weather - but perhaps we can return it as a humble Forcastable, because nobody outside the method creating it actually cares?
I don't really see a reason to explicitly downcast to an interface, but there are two situations I see about casting to an interface: when upcasting (when you don't know in advance if the object you're working with implements the interface) and the second is implicit casting (when you're calling code that operates on the interface only).
When you invoke a legacy method that returns Object or a very bad designed API. In these cases if you can't refactor the method (if it's an old version of Hibernate for instance) you have no other option than casting. I use to create wrappers over this kind of methods to generify them. Once they're generified you can remove all the casts.