我知道.Net中的接口定义了接口和继承它的类之间的契约。刚刚完成了一个大量使用数据访问层接口的项目,它让我思考。 。 。最重要的是什么?当我不得不向DAL添加一个新方法时,我必须在接口中创建方法签名,并将其添加到继承接口的类,当然还有DAL的方法,从而创建“额外的工作”。什么是关于界面的大问题,为什么我想为自己创造额外的工作?
答案 0 :(得分:9)
界面有什么重要意义?
定义合约后,您可以更换实现,而无需担心破坏其余代码。
考虑在.NET中使用List<T>
的性能较差的代码的情况。如果您使用List<T>
的硬实现,那么您很可能会通过更改实现来破解更多代码。
如果您使用IList<T>
或IEnumerable<T>
,则可以List<T>
替换LinkedList<T>
(或实施所选界面的任何内容)并在一个位置修复问题而不是必须触摸你的所有代码。
最后......关于 Polymorphism 。
答案 1 :(得分:3)
最重要的IMO是接口不像特定的继承层次结构那样依赖于类,因此它们比实现抽象接口的类灵活得多。通过使用接口而不是具体类,您可以使用更松散耦合的系统。更改实现很容易:只需提供实现所需接口的任何其他类。
答案 2 :(得分:3)
如果您有两个类,两个不同的数据访问层类具有不同的实现(可能是SQL Server和CouchDB),那么拥有一个标准接口(它们都实现)将意味着您有一种与这些类交互的标准方法
您可以“热交换”不同的数据类,而不必知道具体的底层实现。
答案 3 :(得分:2)
使用Interfaces的一个原因是在类之间创建松耦合。
例如,如果您在类构造函数中传递接口而不是实际的类,则允许更松散的耦合。任何人都可以继承接口并实现自己的实现。
答案 4 :(得分:2)
foreach (object obj in myArray)
{
// distroy all IDisposable objects
if (obj is IDisposable)
(obj as IDisposable).Dispose();
// ends initialization of all ISupportInitialize objects
else if (obj is ISupportInitialize)
(obj as ISupportInitialize).EndInit();
}
因此,如果某些不同的对象实现了相同的接口,那么该接口可以保证每个接口都有一些常用的方法,如本界面所述。
这在对象集合中非常有用。你知道所有动物(人类包容性)都可以吃。所以你知道,如果在汽车里你有动物,它们每个都可以吃,人类,鼠标或 Zebra ......
所以接口 IEatable :)...
答案 5 :(得分:1)
当我在学校时,我没有得到接口甚至迭代器的美妙,因为我们试图解决的问题可以在不使用抽象的情况下以1/2的代码完成。
通常,软件模式是出于行业的实际需要而产生的。我认为接口在某些时候被认为几乎是一种模式。
由于时间限制,学校项目的教学内容有限。
答案 6 :(得分:0)
如果您要更改数据的存储方式,您只需创建一个实现DAL接口的新类,您的应用程序就可以立即使用它。您不需要搜索应用程序中的所有使用实例,并用新的替换旧类。
例如,您也可以使用IoC(在Castle Windsor或其他库的帮助下)通过配置插入特定的数据访问风格,而无需重新编译您的应用程序。
答案 7 :(得分:0)
在您的示例中,只有一个实现接口的类,您没有看到好处。如果您有10个类都实现了该接口,您将立即看到优势。
如果你有一个IFoo集合,你可以将任何实现IFoo的类粘贴到该集合中,并在每个对象上调用相同的Bar()方法。在实现它的每个类中,Bar()的实现可能会有很大的不同。
答案 8 :(得分:0)
简单来说,界面用于在两个组件之间提供清晰的分离点。您可以设计针对接口(List<T>
)进行设计,并且能够使用任何实现接口的对象,而不是将组件设计为针对单个类型(例如IList<T>
)工作。
当您开始使用依赖注入和模拟测试时,这种分离非常有用。
答案 9 :(得分:0)
考虑接口的更好方法是作为对象(或服务)与该服务用户之间的契约。在您的DAL问题中,接口的真正价值在于能够用实现接口的不同实现替换实现接口的类。所以说你的DAL实现是特定于SQL Server的,但现在你需要MySQL支持。您编写了与MySQL对话的接口的另一个插件,将其插入,并且使用DAL的代码不需要更改。优点是客户端代码,而不是实现。
它还有助于测试,允许您在执行测试时插入模拟所需行为的伪造或模拟实现。
答案 10 :(得分:0)
我可以使用接口使我的代码更易于测试。
如果我有一个ManagerClass
public class PersonManager
{
public PersonManager(IPersonRepository repository)
{
this.Repository = repository;
}
private IPersonRepository Repository{get;set;}
public Person ChangeUsername(string username)
{
Person person = this.Repository.GetByUsername(username);
person.Username = username;
this.Repository.Save(person);
return person;
}
}
发布代码将使用一个将调用数据库的存储库对象,但对于我的单元测试,我想隔离数据库的依赖性,以便创建一个实现我的接口的模拟存储库:
public class MockPersonRepository : IPersonRepository
{
public Person GetByUsername(string username)
{
return new Person();
}
public void Save()
{}
}
当我编写单元测试时,我可以传入模拟:
[Test]
public void ChangeUserName_NewUsername_ExpectUpdateUsername()
{
//Arrange
var manager = new PersonManager(new MockPersonManager());
//Act
Person person = manager.ChangeUsername("bob");
//Assert
Assert(AreEqual("bob", person.Username);
}
我现在经理测试我的ChangeUsername方法已经更新了用户名,而没有与数据库交谈