tags:

views:

159

answers:

3

I'm working through the Composite Application Guidance and often come across instantiation of an object of type interface e.g.:

IShell shell = new Shell();

instead of type class:

Shell shell = new Shell();
  • What are the differences between these two?
  • Why is the first way used at all (since the second shell object can be used anywhere an IShell interface is specified, right?)
+1  A: 

The obvious difference is that the first allows you to use shell as an IShell only, the second allows you to use all the features of Shell which happen to also include those of IShell.

Perhaps you could take the view off a maintainer.

The first is saying what we need is an instance of something supporting IShell, and we can change it to some other object if we like.

The second is saying we must have specifically a Shell object for some feature it provides.

Greg Domjan
+2  A: 

You might want to do that if the class has an explicit implementation of an interface method. Consider this example:

public interface ISomething { void Action(); }
public interface ISomethingElse {void Action(); }
public class Something : ISomething
{
    public void Action()
    {
    }
    void ISomething.Action()
    {
    }
}
public class Something2 : ISomething, ISomethingElse
{
    void ISomething.Action()
    {
    }
    void ISomethingElse.Action()
    {
    }
}

If you want ISomething.Action to be called on Something, then you use have to call it through an ISomething variable. Even in Something2, the Action method is hidden if you don't do it through the interface.

That said, you usually want to avoid having implementations like that. I doubt a framework class would force you into that, but that would be the scenario to declare it with the interface.

Update 1: To clear it up a bit, some extra code on how to get to the methods:

Something some = new Something();
some.Action(); //calls the regular Action
ISomething isome = some;
isome.Action(); //calls the ISomething.Action
((ISomething)some).Action(); //again, calls ISomething.Action

Something2 some2 = new Something2();
some2.Action();//compile error
((ISomething)some2).Action(); //calls ISomething.Action
((IsomethingElse)some2).Action(); // calls ISomethingElse.Action
eglasius
that's wild that you can have two identical methods in a class, one for when the object is an instance of the class and one for when it is an instance of the interface, trying to think of when that would be useful...
Edward Tanguay
@Edward when you implement 2 interfaces that happened to use the same method name - haven't actually needed it at all, I just know it is there in case I face that ...
eglasius
so that means that I can instantiate a class that implements an interface, and that object then does NOT implement the interface's methods (your second example), that seems counter-intuitive to the point of interfaces, namely, that if a class implements an interface, it implements all its methods
Edward Tanguay
it seems odd that you can "instantiate an interface", I've always understood interfaces as "contracts" that classes use to prove they have a certain structure and can be used in certain ways
Edward Tanguay
@Edward they are still contracts, I updated my answer with samples on how to use it. You are still working with the same instance, the difference is that you are telling it to call the Action for the ISomething contract. If it implemented another Action method of other interface, you can call it too
eglasius
@Freddy they still function as contracts but they have real methods attached to them that execute code, that is different than my conception of them up to this point, your casting example is interesting, still don't understand why/when they would be used in real apps though
Edward Tanguay
@Freddy, researching explicit interface implementation a bit, I came across the advice "avoid it when you can" more than once, but nice to know it exists, thanks for the clear explanation
Edward Tanguay
@Edward completely agree, only use them if you ever arrived into a forced situation where both interfaces you are implementing has the same method name (forced, as in you don't control the interfaces and need to implement both in different ways)
eglasius
+1  A: 

With your first example, you can only use the functionality specified in IShell within your sourcecode, with the second example, you can also use additional functionality of a Shell object that is not defined in the interface.

The first solution offers more flexibility if you need to replace the Shell object with a different object ShellEx, that has the same functionality, but a different implementation. For this you would only need to change

IShell shell = new Shell();

to

IShell shell = new ShellEx();

The rest of your code does not need to be changed.

The second solution enables you to use the complete functionality of the Shell object.

You will have to decide on a case by case base, which solution is preferrable in the current situation.

Treb