I have used a lot of abstract classes both for polymorphism, and obviously inheriting common function in subclasses.
I'm trying to use interfaces more. Yes, it's also use for polymorphism..for example using an IMyInterface param in a method that can take any subclass that implements IMyInterface.
Ok, now the thing I don't get though is why we should or always need to define our variables as IMyInterface instead of a type that has implemented that interface.
Example, take a look at this article:
http://weblogs.asp.net/sfeldman/archive/2008/02/14/understanding-ioc-container.aspx
Ok, specifically this:
17: private static void AppCode()
18: {
19: ConsoleLogger logger = new ConsoleLogger();
20: Gadget gadget = new Gadget(logger);
21: gadget.TurnOn();
22: gadget.TurnOff();
23: }
24: }
25: }
AppCode method (lines 19-22) is what we are interested in. A few question can be raised at this point:
1. Why logger is of type ConsoleLogger and not ILogger? Isn't this wrong?
2. Why gadget is of type Gadget and not IGadget? Same smell?
3. What if we need to move logger implementer to a different layer than the ConsoleApp?
Here's the thing for me, I don't get why it's not a problem to just use the type Gadget and ConsoleLogger concrete methods. Why in this top layer does it still need to be a var of type ILogger and IGadget? I mean at this point I'm not seeing any need for polymorphism..but I"m missing the boat I guess here in my learning process.
Can someone explain why everyone wants to create interface params in your top layers for variables and assigning that variable to a type that has implemented that interface? Why not just Gadget and ConsoleLogger, the very concrete class you want to use in the first place? Yes Gadget and ConsoleLogger meet the contracts of the ILogger and IGadget...but I must be missing another reason here..fundamental reason.
If I make no sense, it's because I don't really know how 开发者_如何转开发to describe my question but I feel this is pretty clear. Why use interface variables in a case like this?
It's almost like what I've seen out there is once you need to use a concrete type that has implemented an Interface that it looks to me that you should always set it to an interface variable, not a variable type of that subclass. Is this right?
Here's the thing for me, I don't get why it's not a problem to just use the type Gadget and ConsoleLogger concrete methods. Why in this top layer does it still need to be a var of type ILogger and IGadget? I mean at this point I'm not seeing any need for polymorphism..but I"m missing the boat I guess here in my learning process.
The whole idea of inversion of control
is to get the dependencies out of the classes, that uses them. Accodring the code you've pasted - the Program
is highly coupled to specific classes. I even say - it is coupled to implementation
!
So, when you rewrite that Program
on using of interfaces - you are free in the future to use any interface impementation you want. Let's suppose you wanted to change ConsoleLogger
to SyslogLogger
, or even to CompositeLogger
which writes to several storages.
With dependencies inverted (moved outside the class) - you can do that very simple and without any modifications. As usual - dependency container configuration is some of human-readable format, xml, for example. So for changing of your program behaviour (move from one - to another logger) - only thing you need is just to change one line in config file.
http://en.wikipedia.org/wiki/Inversion_of_control - this article describes the same thing but in correct english ))
UPD:
in that sample - Program
depends on ConsoleLogger
class. This means that the dependency is "inside" the class program. So when you move this dependency outside (for example - by passing the ConsoleLogger
by function parameter) - it called inversion. And now that dependency is outside. Outside == Program
now depends on some ConsoleLogger
interface, not the class itself, and now Program
does not take care how to instantiate that class object.
And dependency container
is just a software that helps you to organize the relations/dependencies in a handy manner (as usual it is tree, dependency tree).
精彩评论