所以我对C#和使用接口仍然很新,当我认为我理解它们时,我意识到我并不完全。我发现我在寻求一些澄清的困惑是,当你创建一个接口,并且有一个继承自它的类
public Interface ISomeInterface
{
//some methods/properties
}
public class FooClass : ISomeInterface
{
//implemented ISomeInterfaces methods/properties
}
您在程序中的某个实现中使用此类对象
public class BarClass
{
private ISomeInterface _someInterface;
public BarClass(ISomeInterface someInterface)
{
_someInterface = someInterface;
}
//rest of class
}
我的困惑是为什么我会这样设置它。我以为我会实例化一个类型为FooClass的新对象,并在构造函数中使用类型为FooClass的对象:
public class BarClass
{
private FooClass _fooClass;
public BarClass(FooClass fooClass)
{
_fooClass = fooClass;
}
//rest of class
}
理解这一点我缺少什么?我不认为我会直接声明接口的对象?
提前致谢。
答案 0 :(得分:7)
我们的想法是BarClass
不应与ISomeInterface
的具体实施紧密结合。
如果您使用此:
public BarClass(FooClass fooClass)
这意味着BarClass只能使用这个特定的FooClass实现,而不能用于任何其他实现。而如果您使用:
public BarClass(ISomeInterface fooClass)
现在BarClass
已不再与FooClass
紧密耦合。这意味着BarClass
的使用者现在可以传递他想要的接口的任何实现,只要它遵守定义的合同(接口)。因此,如果他想要FooClass
他传递FooClass
的实例,但如果他对FooClass
不满意,他可以编写自己的实现并将其传递给构造函数并从角度来看BarClass
这是绝对透明的(不需要修改)。
类之间的弱耦合是OOP最基本的方面之一,因为它允许您轻松地将一个组件替换为另一个组件,而无需重写整个应用程序。
答案 1 :(得分:1)
假设FooClass向数据库写了一些东西。您想要测试BarClass而无需实际设置数据库。如果您创建了一个实现相同界面的不同TestFoo,您可以伪装成数据库并更轻松地测试您的类; BarClass不必知道它没有与'真正的'FooClass交谈。
答案 2 :(得分:0)
你有C / C ++背景吗?那你应该知道
private ISomeInterface _someInterface;
将写为
private:
ISomeInterface& _someInterface;
在C ++中(假设你有一个名为ISomeInterface的抽象基类)。
这意味着您存储对实现ISomeInterface的对象的引用,而不是这样的对象本身。这样做的好处是你可以将任何对象传递给实现ISomeInterface的BarClass,这样可以提供更大的灵活性,例如:用于单元测试。
答案 3 :(得分:0)
通过使用接口定义而不是具体实现,您的代码现在更加松散耦合。该技术用于依赖注入。
此外,当您需要以不同方式实现FooClass
时,这会派上用场。如果您使用了具体实现,则需要在声明FooClass
的位置更改代码。针对界面进行编程可以保护您免受此类更改的影响。
答案 4 :(得分:0)
编程到ISomeInterface而不是FooClass的一个主要好处是,您可能可能会更改FooClass的实现。例如,考虑一个数据库驱动的博客应用程序:
interface IBlogStorage{
getPosts();
}
然后你有一个类:
class XMLBlogSotrage: IBlogStorage{}
并假设您实现了界面的所有内容。稍后,您认为XML太慢而您想使用RDBMS,然后:
class MsSQLBlogStorage:IBlogStorage{}
在这种情况下,您无需更改其他代码中的任何内容,只需创建一个新类并将其插入即可!那些已经存在的代码,不需要打扰存储在哪里。
答案 5 :(得分:0)
另一种思考接口和类之间相互作用的方法是颠倒它们。这意味着首先从课程开始。假设您有几个类公开了一个名为“Sort()”的方法。然后你有另一个类,它有一个方法需要引用这些类,然后调用它们的“Sort()”方法。您可以创建并附加这些类的接口,而不是使用具有不同参数的多个方法(非常快速,因为这些类已包含实现)。
A.Sort()
B.Sort()
C.Sort()
interface ISortable {void Sort();}
A : ISortable
B : ISortable
C : ISortable
D.SortSomething(ISortable foo)
{
foo.Sort()
}
也许这太抽象了。我最喜欢使用接口是让我的类能够参与foreach循环。
class SomeCollection : IEnumerable
{
List<SomeItem> _items = new List<SomeItem>();
// This is the only code I need to enable this class to participate in foreach loop.
public Enumerator GetEnumerator()
{
return _items.GetEnumerator();
}
}
一旦发现接口如何简化代码,您甚至可以在编写类之前开始创建接口。