Your code isn't intantiating an IBankAccount object. Interfaces can't be instantiated because they are abstract (incomplete) types. Your code is instantiating a VenusBank object as
an IBankAccount type, and a JupiterBank object as
an IBankAccount type. When a type implements interfaces, it allows its objects to be treated as any of its interface types. Using
VenusBank account1 = new VenusBank()
you can call any method defined in VenusBank or IBankAccount. Using
IBankAccount account1 = new VenusBank()
you can only call methods defined in IBankAccount. The helpful formula for me is: interfaces let you treat a single object as though it we're of different types.
The advantage of programming to interfaces in this way, is that your client code doesn’t have to know anything about the specific type of object it is using (i.e., the VenusBank or JupiterBank object), and it doesn’t have to know anything about the classes that implement those objects either (i.e., the VenusBank or JupiterBank class). This enables you to reduce “implementation dependencies” (or high coupling) between your client and your apps other components, making your app less "fragile" as a result. The VenusBank and JupiterBank class can change their properties and methods over time, but since they implement IBankAccount, you are guaranteed that you can always treat a VenusBank or a JupiterBank object as an IBankAccount type without breaking your app. Also, you might want to extend your app to use additional bank objects, like PlutoBank and UranusBank. All you would have to do is implement a factory method that returns an IBankAccount and you could obtain any type of account object you like without ever having to change your account object creation code.