Polymorphism is the ability to change the structure of an object and how it interacts with the application. Polymorphism can be used through implicit casting, upcasting/downcasting and casting to/from an interface. We use polymorphism in programs mainly as an encapsulation tool.
Say we are instantiating a Custodian type object.
When we use the object we can see all the members we have available to us.
But let's change the type of object that the local variable is. Since Employee is a parent class of the Custodian this works.
Notice that the members we had available to us when the type was Custodian (like CleanRestroom) are now gone.
Doing this is considered implicit casting because there is no explicit (forced) casting going on. We would do this if there was any reason to treat the object as an Employee object like adding it to a list that only accepts Employee objects.
Let's bring our custodian back from the previous example.
In the previous example we implicitly casted the Custodian type to an Employee type, but we can also explicitly cast it by using the as keyword.
This gives us the same result (the Custodian members are gone) as we had in the previous example. The custodian object is now more "generic" than it was before.
Another way of achieving the same result is shown below. We can define a local variable with the more generic type and then assign it to the casted type.
Say we have a of type ICleanable that is an instance of the Booth class.
When we look at the members we have available to us we can see that we only have members that are related to being cleanable; a very "generic" bunch of members.
But we know that the Booth has other members that are more specific to Booth objects we want to access. What we can do then is us the as keyword to make the ticketBooth a more specific Booth type.
Now we have access to all of the members related to Booths. The example below achieves the same result.