我已经使用了很多抽象类来实现多态性,显然在子类中继承了常用函数。
我正在尝试更多地使用接口。是的,它也用于多态...例如在一个方法中使用IMyInterface参数,该方法可以采用任何实现IMyInterface的子类。
好的,现在我不知道的是为什么我们应该或者总是需要将我们的变量定义为IMyInterface而不是实现该接口的类型。
示例,请看一下这篇文章:
http://weblogs.asp.net/sfeldman/archive/2008/02/14/understanding-ioc-container.aspx
好的,特别是这个:
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?
对我来说这是件事,我不明白为什么只使用Gadget和ConsoleLogger类型的具体方法不是问题。为什么在这个顶层中它仍然需要是ILogger和IGadget类型的var?我的意思是在这一点上我没有看到任何多态性的需要..但是我想在我的学习过程中错过了这条船。
有人可以解释为什么每个人都希望在顶层为变量创建接口参数并将该变量分配给已实现该接口的类型?为什么不只是Gadget和ConsoleLogger,你想要首先使用的具体类?是Gadget和ConsoleLogger符合ILogger和IGadget的合同......但我必须在这里错过另一个原因......基本原因。
如果我没有意义,那是因为我真的不知道如何描述我的问题,但我觉得这很清楚。为什么在这种情况下使用接口变量?
这几乎就像我所看到的那样,一旦你需要使用一个已经实现了一个接口的具体类型,我认为你应该总是将它设置为接口变量,而不是该子类的变量类型。这是对的吗?
答案 0 :(得分:6)
对我来说这是件事,我不明白为什么只使用Gadget和ConsoleLogger类型的具体方法不是问题。为什么在这个顶层中它仍然需要是ILogger和IGadget类型的var?我的意思是在这一点上我没有看到任何多态性的需要..但是我想在我的学习过程中错过了这条船。
inversion of control
的整个想法是从使用它们的类中获取依赖项。根据您粘贴的代码 - Program
与特定类高度耦合。我甚至说 - 它与implementation
!
因此,当您在使用接口时重写Program
时,您将来可以自由使用任何所需的接口。假设您想要将ConsoleLogger
更改为SyslogLogger
,甚至更改为CompositeLogger
,它会写入多个存储空间。
将依赖项反转(移到类外) - 您可以非常简单地进行操作而无需任何修改。像往常一样 - 依赖容器配置是一些人类可读的格式,例如xml。因此,为了改变您的程序行为(从一个记录器移动到另一个记录器) - 您只需更改配置文件中的一行。
http://en.wikipedia.org/wiki/Inversion_of_control - 这篇文章描述了同样的事情,但用正确的英文))
<强> UPD 强>:
该样本中的 - Program
取决于ConsoleLogger
类。这意味着依赖是在类程序“内部”。因此,当您将此依赖项移到外部时(例如 - 通过函数参数传递ConsoleLogger
) - 它会调用反转。而现在依赖是在外面。外部== Program
现在依赖于某个ConsoleLogger
接口,而不是类本身,现在Program
并不关心如何实例化该类对象。
dependency container
只是一个软件,可以帮助您以方便的方式组织关系/依赖关系(像往常一样,它是树,依赖树)。