为什么我应该去C#中的接口,当我可以直接实现的方法

我知道这是一个非常基本的问题,但一个采访者以非常诡计的方式问我,我很无奈:(

我只知道一个接口的物质或理论定义,并在我所从事的许多项目中实现它。 但是我真的不明白为什么,以及如何有用。

我也不明白界面中的一件事。 即例如,我们使用

conn.Dispose(); 在终于阻止。 但我没有看到该类正在实现或inheritanceIDisposable接口( SqlConnection )类的意思。 我想知道如何才能调用方法名称。 在同样的事情中,我不理解Dispose方法是如何工作的,因为我们需要用我们自己的实现来实现所有接口方法的函数体。 那么接口如何被接受或命名为契约? 直到现在,这些问题一直在我的脑海中浮现,坦率地说,我从来没有看到任何能够以我能理解的方式来解释我的问题的好线索。

像往常一样MSDN看起来非常可怕,没有一个单一的路线是明确的( 民间,善意的借口谁进入高层次的发展,我强烈地感到,任何代码或文章应该达到任何人看到它的头脑,因此像许多人说,MSDN没有用 )。

采访者说:

他有5种方法,他很乐意直接在课堂上实现它,但如果你必须去抽象类或接口,你select哪一个,为什么? 我确实回答了我在各种博客上看到的抽象类和接口的优缺点,但是他并不确信,他正在试图理解“Why Interface”。 一般来说,“为什么抽象类”,即使我只能执行一次同样的方法,也不会改变它。

我没有看到networking上的任何地方,我可以得到一篇能够清楚地解释接口及其function的文章。 我是那些许多程序员之一,他们仍然不知道接口(我知道我使用的理论和方法),但并不满足于我明白的理解。

当你想要创build类似的接口时,接口是非常好的:

  using System; namespace MyInterfaceExample { public interface IMyLogInterface { //I want to have a especific method that I'll use in MyLogClass void WriteLog(); } public class MyClass:IMyLogInterface { public void WriteLog() { Console.Write("MyClass was Logged"); } } public class MyOtherClass :IMyLogInterface { public void WriteLog() { Console.Write("MyOtherClass was Logged"); Console.Write("And I Logged it different, than MyClass"); } } public class MyLogClass { //I created a WriteLog method where I can pass as parameter any object that implement IMyLogInterface. public static void WriteLog(IMyLogInterface myLogObject) { myLogObject.WriteLog(); //So I can use WriteLog here. } } public class MyMainClass { public void DoSomething() { MyClass aClass = new MyClass(); MyOtherClass otherClass = new MyOtherClass(); MyLogClass.WriteLog(aClass);//MyClass can log, and have his own implementation MyLogClass.WriteLog(otherClass); //As MyOtherClass also have his own implementation on how to log. } } } 

在我的例子中,我可以是编写MyLogClass的开发人员,其他开发人员可以创build他们的类,当他们想要login时,他们实现接口IMyLogInterface 。 就像他们问我在MyLogClass使用WriteLog()方法需要实现什么MyLogClass 。 他们将在界面中find答案。

接口是实施者必须遵循的合同。 抽象类允许合约加上共享的实现 – 接口不能有的东西。 类可以实现并inheritance多个接口。 类只能扩展一个抽象类。

为什么界面

  • 您没有默认或共享的代码实现
  • 你想分享数据合同(networking服务,SOA)
  • 每个接口实现者都有不同的实现( IDbCommand具有SqlCommandOracleCommand ,它们以特定的方式实现接口
  • 你想支持多重inheritance 。

为什么抽象

  • 您有默认或共享的代码实现
  • 你想尽量减less代码重复
  • 您想轻松支持版本控制

我使用接口的一个原因是因为它增加了代码的灵活性。 比方说,我们得到了一个以类types为Account的对象作为参数的方法,比如:

  public void DoSomething(Account account) { // Do awesome stuff here. } 

这个问题是,方法参数被固定为一个帐户的实现。 如果您不需要任何其他types的帐户,这很好。 以此示例为例,该示例使用帐户界面作为参数。

 public void DoSomething(IAccount account) { // Do awesome stuff here. } 

这个解决scheme并不是针对一个实现而固定的,这意味着我可以将它传递给一个SuperSavingsAccount或一个ExclusiveAccount(实现IAccount接口),并为每个实现的帐户获得不同的行为。

一个词 – 因为多态

如果你“编程接口,而不是一个实现”比你可以注入不同的对象共享相同的接口(types)的方法作为参数。 这样,你的方法代码就不会与另一个类的任何实现结合在一起,这意味着它始终可以与同一接口的新创build的对象一起工作。 (打开/closures原则)

  • 研究dependency injection,并肯定阅读devise模式 – GOF 的可重用面向对象软件元素

C#没有鸭子打字 – 只是因为你知道某个方法是通过一组具体的类来实现的,并不意味着你可以把它们全部用同样的方法来调用。 实现一个接口允许你把实现它的所有类视为同一types的东西,关于接口定义的内容。

你只能从一个抽象类inheritance。 您可以从多个接口inheritance。 这决定了我在大多数情况下使用的东西。

抽象类的优点是你可以有一个基本的实现。 但是,在IDisposable的情况下,默认的实现是无用的,因为基类不知道如何正确地清理东西。 因此,一个界面会更合适。

通过一个界面你可以做到以下几点:

1)创build分离的接口,提供不同的实现方式,允许更紧密的接口。

2)允许在接口之间使用相同名称的多个方法,因为嘿,你没有冲突的实现,只是一个签名。

3)您可以独立版本和分离您的界面,确保合同得到满足。

4)你的代码可以依靠抽象,而不是凝结,允许智能dependency injection,包括注入testingMocks等

我敢肯定,还有更多的原因,这些只是less数。

一个抽象类允许你有一个部分具体的基础来工作,这不是一个接口相同,但有自己的特质,如使用模板方法模式创build部分实现的能力。

抽象类和接口都是合约。

合同的概念是指定一些行为。 如果你说你已经执行你已经同意了合同。

抽象的界面的select是。

抽象类的任何非抽象的后代将执行合同。

任何实现该接口的类都将执行该合同。

所以当你想指定一些行为时,所有的后代都必须实现并保存自己定义的一个单独的接口,所以当你使用抽象的时候,现在满足这个有效聚合的所有东西都必须是一个后代。

我相信在提出这个问题的时候已经有很多的血液已经stream了出来,许多人试图通过解释没有正常人能理解的类似机器人的术语来解决这个问题。

所以首先。 了解为什么界面和为什么抽象你需要了解他们是什么。 我个人应用Factory Class时学到了这两个。 你在这个环节find了一个很好的方法

现在让我们根据我已经提供的链接进行挖掘。

你有车辆类可能会改变用户的要求(如添加卡车坦克飞机等,并给我们有

 public class clsBike:IChoice { #region IChoice Members public string Buy() { return ("You choose Bike"); } #endregion } 

 public class clsCar:IChoice { #region IChoice Members public string Buy() { return ("You choose Car"); } #endregion } 

并且都有Contract IChoice,简单地说我的类应该有Buy方法

 public interface IChoice { string Buy(); } 

现在,您会看到,该接口只强制执行方法Buy()但让inheritance类决定在执行该操作时要执行的操作。 这是Interface的限制,使用纯粹的接口,最终可能会重复一些我们可以使用abstact自动实现的任务。 就我们的例子来说,购买每辆车都有折扣。

 public abstract class Choice { public abstract string Discount { get; } public abstract string Type { get; } public string Buy() { return "You buy" + Type + " with " + Discount; } public class clsBike: Choice { public abstract string Discount { get { return "10% Discount Off"; } } public abstract string Type { get { return "Bike"; } } } public class clsCar:Choice { public abstract string Discount { get { return " $15K Less"; } } public abstract string Type { get { return "Car"; } } } 

现在使用Factory类,你可以实现同样的事情,但是在使用抽象的时候,你让基类执行Buy()方法。

总结: 接口契约让inheritance类做的实现,而抽象类契约可能初始化实现(可以通过inheritance类重写)

在这里输入图像说明

所以在这个例子中,PowerSocket并不知道其他对象的其他任何内容。 这些对象都依赖于PowerSocket提供的Power,所以它们实现了IPowerPlug,这样就可以连接到它。

接口是有用的,因为它们提供对象可以使用的协议,而不需要彼此了解其他任何信息。

接口允许类devise者为最终用户提供可用的方法。 它们也是多态的一个组成部分。

我不会把抽象类的接口的定义发布出来,因为我认为你非常了解这个理论,并且我假设你知道SOLID原则,所以让我们来实践一下吧。

正如你所知道的接口不能有任何代码,所以这个优点是很容易理解的。

如果你需要初始化你的类的属性提供一个构造函数,或者你想提供部分的实现一个抽象类将是一个很好的适合接口,这将不允许你这样做。

所以在一般情况下,当你需要提供一个构造函数或任何代码给客户端时,你应该更喜欢抽象类来接口,这将inheritance/扩展你的类

抽象类是为相关实体创build的,因为接口可以用于不相关的实体。

例如,如果我有两个实体说动物和人,那么我将去接口,如果我要详细说虎,狮子,并想与动物关系,那么将select动物抽象类。

将如下所示

  Interface ____|____ | | Animal Human Animal (Abstract class) __|___ | | Tiger Lion