You are addressing two related questions: Which interface to use to access an object (for this, I see class
also as a kind of interface).
If you know in advance that you will need to access Pen
methods, you should type your variable as Pen
in the first place. But on the other hand, you should refer to objects by their interfaces (from Effective Java by Joshua Bloch) so if you do not need the access to Pen
methods, don't access it via that class.
Your second question is about creating objects to access the classes methods. But this approach is not what object oriented programming is made for: you create a class so you can access the inside data (in the object) only via the classes' methods. So your idea of first creating a Gift
instance and then creating a Pen
instance again for more methods is less than ideal because the methods of Pen
also need more data, that have to be initialized at some point in time (usually at the construction of Pen
). Where do you get that data from if you only have a Gift
instance available?
If you have the data in the first place, why did you not create a Pen
right away?
You could also provide a factory method for Pen
that creates a new instance from a Gift
instance plus all the extra data necessary for a Pen
instance.
This is not always an ideal solution, so the answer to your question is neither yes or no, but: it depends. Depending on the actual problem you want to solve, the best solution to pick could vary, so if you have an actual problem to solve, you should add it to your question to get more advice, or add another question.
UPDATE: (per OPs request)
Can you just tell me why we use Gift gift = new Pen()
?
As you do not supply any surrounding code, I cannot name the exact reason, but in the link above you find an explanation why you should use the "least specific" interface.
For this we see classes also as interfaces (with an implementation). Also a method is kind of a contract with the implementer of an interface. So if you use the least specific interface, you do not rely on the actual implementation, but on the contract of the methods of that interface. So you can easily change the implementation later if that is necessary.
A good and very commonly used example for this is e.g. the java.util.List
interface. You just want to know that (basically) you are operating on an ordered collection. As "user" of the interface you don't care how the list is ordered, or if it is backed by an array or a linked list (or lazy loaded from a database, etc.). If you used java.util.ArrayList
you always have to load everything into an array, or at least pretend that you do that - if you inherit from that class and override methods, and that would be super complex to handle for code maintainers.
Why we use Downcasting?
A good use case for this (but probably not the only one) is: Quite often you have existing code that you want to use that expects objects of a certain class
or interface
. But the existing class doesn't fit your needs, so you inherit of or implement what is existing and expected. You create a more specific implementation. But you cannot or don't want to change the existing code, so you downcast your implementation to whatever is needed. Often the inherited classes do not even implement new methods, but just override some existing ones.
I want to understand the concept of Downcasting, Polymorphism in Java (Why to use and When to use it)
Polymorphism is not always helpful, the past showed that it also can be a burden, especially for code that is maintained and extended over a longer period of time, but also for new code that is just badly designed. It's hard to give a general advice, but it's good that you try to learn about it.
I would recommend that you read at least the chapter Favor composition over inheritance in the book "Effective Java", but can recommend the whole book. It's not only useful for Java developers, but OOP in general (the examples and specific chapters are Java only).