C# 我想我漏掉了一些东西;“编程到接口”;概念

C# 我想我漏掉了一些东西;“编程到接口”;概念,c#,interface,C#,Interface,所以我对C#和使用接口还是很陌生,当我认为我理解它们时,我意识到我并不完全理解。我发现这里需要澄清的困惑是,当您创建一个接口并从中继承一个类时 public Interface ISomeInterface { //some methods/properties } public class FooClass : ISomeInterface { //implemented ISomeInterfaces methods/properties } 您可以在程序的某个实现中使用这个类对

所以我对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
}
理解这一点,我遗漏了什么?我没想到我会直接声明接口的对象


提前感谢。

我们的想法是,
BarClass
不应该与
ISomeInterface
的特定实现紧密耦合

如果您使用此选项:

public BarClass(FooClass fooClass)
这意味着BarClass只能与这个特定的FooClass实现一起工作,而不能与其他任何东西一起工作。鉴于如果您使用:

public BarClass(ISomeInterface fooClass)
现在,
BarClass
不再与
FooClass
紧密耦合。这意味着
BarClass
的使用者现在可以传递他想要的接口的任何实现,只要它遵守定义的契约(接口)。因此,如果他想要
FooClass
,他会传递一个
FooClass
的实例,但是如果他对
FooClass
不满意,他可以编写自己的实现并将其传递给构造函数,从
BarClass
的角度来看,这是绝对透明的(不需要修改)


类之间的弱耦合是OOP最基本的方面之一,因为它允许您轻松地用一个组件替换另一个组件,而无需重写整个应用程序。

其思想是,
BarClass
不应与
ISomeInterface
的特定实现紧密耦合

如果您使用此选项:

public BarClass(FooClass fooClass)
这意味着BarClass只能与这个特定的FooClass实现一起工作,而不能与其他任何东西一起工作。鉴于如果您使用:

public BarClass(ISomeInterface fooClass)
现在,
BarClass
不再与
FooClass
紧密耦合。这意味着
BarClass
的使用者现在可以传递他想要的接口的任何实现,只要它遵守定义的契约(接口)。因此,如果他想要
FooClass
,他会传递一个
FooClass
的实例,但是如果他对
FooClass
不满意,他可以编写自己的实现并将其传递给构造函数,从
BarClass
的角度来看,这是绝对透明的(不需要修改)


类之间的弱耦合是OOP最基本的方面之一,因为它允许您轻松地用另一个组件替换一个组件,而无需重写整个应用程序。

假设FooClass向数据库写入了一些内容。您希望在不必实际设置数据库的情况下测试BarClass。如果您创建了一个实现相同接口的不同TestFoo,那么您可以假装是数据库,更容易地测试您的类;BarClass不必知道它没有与“真正的”FooClass对话。

假设FooClass向数据库写入了一些内容。您希望在不必实际设置数据库的情况下测试BarClass。如果您创建了一个实现相同接口的不同TestFoo,那么您可以假装是数据库,更容易地测试您的类;BarClass不必知道它没有与“真正的”FooClass对话。

你有C/C++背景吗?那么你应该知道

private ISomeInterface _someInterface;
将写为

private:
  ISomeInterface& _someInterface;
C++中的p>(假设你有一个抽象的基类叫做ISOMealEdvices)。
这意味着您要存储对对象的引用,而不是对象本身。这样做的好处是,您可以将任何对象传递给实现ISomeInterface的BarClass,这为您提供了更大的灵活性,例如用于单元测试。

您有C/C++背景吗?那么你应该知道

private ISomeInterface _someInterface;
将写为

private:
  ISomeInterface& _someInterface;
C++中的p>(假设你有一个抽象的基类叫做ISOMealEdvices)。
这意味着您要存储对对象的引用,而不是对象本身。这样做的好处是,您可以将任何对象传递给实现ISomeInterface的BarClass,这为您提供了更大的灵活性,例如用于单元测试。

通过使用接口定义而不是具体实现,您的代码现在更松散耦合。此技术用于依赖项注入


此外,当您需要以不同的方式实现
FooClass
时,这也很方便。如果使用具体的实现,则需要在声明
FooClass
的地方进行代码更改。针对接口编程可以使您免受此类更改的影响。

通过使用接口定义而不是具体实现,您的代码现在更加松散耦合。此技术用于依赖项注入


此外,当您需要以不同的方式实现
FooClass
时,这也很方便。如果使用具体的实现,则需要在声明
FooClass
的地方进行代码更改。针对接口编程可以使您免受此类更改的影响。

将接口编程而不是FooClass的主要好处之一是,您可能会更改FooClass的实现。例如,考虑一个数据库驱动的博客应用程序:

interface IBlogStorage{
    getPosts();
}
然后有一个类,如:

class XMLBlogSotrage: IBlogStorage{}
假设您实现了接口的所有功能。后来,您认为XML速度太慢,希望使用RDBMS,然后:

class MsSQLBlogStorage:IBlogStorage{}
在这种情况下,您不需要更改其他代码中的任何内容,只需创建一个新类并将其插入!