You should look into Inversion of Control:
In such a scenario, you wouldn't write this:
IInterface classRef = new ObjectWhatever();
You would write something like this:
IInterface classRef = container.Resolve<IInterface>();
This would go into a rule-based setup in the container
object, and construct the actual object for you, which could be ObjectWhatever. The important thing is that you could replace this rule with something that used another type of object altogether, and your code would still work.
If we leave IoC off the table, you can write code that knows that it can talk to an object that does something specific, but not which type of object or how it does it.
This would come in handy when passing parameters.
As for your parenthesized question "Also, how could you write a method that takes in a object that implements a Interface? Is that possible?", in C# you would simply use the interface type for the parameter type, like this:
public void DoSomethingToAnObject(IInterface whatever) { ... }
this plugs right into the "talk to an object that does something specific". The method defined above knows what to expect from the object, that it implements everything in IInterface, but it doesn't care which type of object it is, only that it adheres to the contract, which is what an interface really is.
For instance, you're probably familiar with calculators and have probably used quite a few in your days, but most of the time they're all different. You, on the other hand, knows how a standard calculator should work, so you're able to use them all, even if you can't use the specific features that each calculator has that none of the other has.
This is the beauty of interfaces. You can write a piece of code, that knows that it will get objects passed to it that it can expect a certain behaviour from. It doesn't care one hoot what kind of object it is, only that it supports the behaviour needed.
Let me give you a concrete example.
We have a custom-built translation system for windows forms. This system loops through controls on a form, and translates text in each. The system knows how to handle basic controls, like the-type-of-control-that-has-a-Text-property, and similar basic stuff, but for anything basic, it falls short.
Now, since controls inherit from pre-defined classes that we have no control over, we could do one of three things:
- Build support into our translation system to detect specifically which type of control it is working with, and translate the correct bits (maintenance nightmare)
- Build support into base classes (impossible, since all the controls inherit from different pre-defined classes)
- Add interface support
So we did nr. 3. All our controls implement ILocalizable, which is an interface that gives us one method, the ability to translate "itself" through a container of translation text/rules. As such, the form doesn't need to know which kind of control it has found, only that it implements the specific interface, and knows that there is a method there it can call to localize the control.