Che*_*hen 61
interface IFlyable
{
void Fly();
}
class Bird : IFlyable
{
public void Fly() { }
}
class Plane : IFlyable
{
public void Fly() { }
}
List<IFlyable> things = GetBirdInstancesAndPlaneInstancesMixed();
foreach(IFlyable item in things)
{
item.Fly();
}
Run Code Online (Sandbox Code Playgroud)
Bird并且Plane,除非是共同的基类Object,但你可以看到使用我们可以grouply对付他们在我们的节目相同的接口,因为它们具有相同的"特性":飞.
Rob*_*ett 32
public interface ISpeaks
{
string Speak();
}
public class Dog : Mammal, ISpeaks
{
public string Speak() { return "Woof!"; }
}
public class Person : Mammal, ISpeaks
{
public string Speak() { return "Hi!"; }
}
//Notice Telephone has a different abstract class
public class Telephone : Appliance, ISpeaks
{
public Person P { get; set; }
public Telephone(Person p)
{
P = p;
}
public string Speak() { return P.Speak(); }
}
[Test]
public void Test_Objects_Can_Speak()
{
List<ISpeaks> thingsThatCanSpeak = new List<ISpeaks>();
//We can add anything that implements the interface to the list
thingsThatCanSpeak.Add(new Dog());
thingsThatCanSpeak.Add(new Person());
thingsThatCanSpeak.Add(new Telephone(new Person()));
foreach(var thing in thingsThatCanSpeak)
{
//We know at compile time that everything in the collection can speak
Console.WriteLine(thing.Speak());
}
}
Run Code Online (Sandbox Code Playgroud)
这很有用,因为我们可以针对接口而不是实现进行编码,因为我们可以在单个类上使用多个接口,所以我们比使用Abstract类更灵活.
Interfaces在某种程度上类定义是相似的,是interface实现它的类之间的一种契约.
接口仅包含方法,属性,事件或索引器的签名.实现接口的类或结构必须实现接口定义中指定的接口成员.
.NET类不能使用多继承.因此,我们依赖于接口,并且类可以实现尽可能多的接口.相反,类继承必须是单一的.例如:
public class Customer : Person, Company {
}
Run Code Online (Sandbox Code Playgroud)
我所知道的任何.NET语言(C#/ VB.NET)都不允许使用此代码.
为了克服这种不足,如果我们可以这样说,我们依赖于接口.
public interface IPerson {
string Name
string Address
string StateProvince
string ZipPostalCode
string Country
long PhoneNumber
}
public interface ICompany {
string CreditTerm
string BillingAddress
string ShippingAddress
string ContactName
long ContactPhoneNumber
long FaxNumber
}
public class Customer : IPerson, ICompany {
// Properties implementations here.
}
Run Code Online (Sandbox Code Playgroud)
通过这种方式,接口就像是一种多重继承的解决方法.
另一方面,接口可以用作方法的契约.假设您有一个ICompany将输入参数作为输入参数的方法.您现在可以确保在ICompany界面中定义属性以在方法中执行您的工作.
public BillCompany(ICompany company) {
// Bill company here...
}
Run Code Online (Sandbox Code Playgroud)
然后,您的Customer类对应于您期望的内容,因为它实现了ICompany接口.
让我们创建另一个类,其定义只会实现IPerson接口.
public class Individual : IPerson {
// Interface implementation here...
}
Run Code Online (Sandbox Code Playgroud)
然后,您的BillCompany()方法无法接受Individual类的实例,因为它不显示公司的要求(属性等).
简而言之,接口是通过契约将方法绑定到可接受的内容(如继承)的好方法.
在使用Interfaces 时确实需要采取一些预防措施,对接口的更改将破坏您的代码,作为在所有实现类中实现新成员的强制规则,而类继承不会.
这有帮助吗?
我喜欢这篇我前几天阅读的博文:http://simpleprogrammer.com/2010/11/02/back-to-basics-what-is-an-interface/
许多人,包括我自己,已经创建了与他们所代表的类具有1对1映射的接口,但这并不总是一件好事,该文章解释了原因.
当您有一个给定的合同想要一个对象履行但您并不真正在乎它们如何履行时,接口就很有用。那是类本身的实现细节。
因此,假设您有一种方法是处理保存请求。它不执行实际的保存操作,仅处理请求。结果,它可以是List<ICanSave>,其中ICanSave是接口。该列表中的对象可以是实现该接口的任何类型。它可以是混合的,也可以仅包含一种类型。您只关心它实现了接口。
public interface ICanSave
{
void Save();
}
Run Code Online (Sandbox Code Playgroud)
在您的方法中,您可能会遇到一些简单的问题,例如
public void SaveItems(List<ICanSave> items)
{
foreach (var item in items)
{
item.Save();
}
}
Run Code Online (Sandbox Code Playgroud)
这些项目如何保存?你不在乎!同样,这是实现接口的类的实现细节。您只希望输入方法的任何类都具有该功能。
您可能拥有一个实现将数据持久保存到文件系统的接口的类。另一个可能会保存到数据库。另一个人可能需要一些外部服务。等等,这留给班级的作者来决定。您甚至可以为单元测试设置一个存根类,而该类根本什么也不做。
那只是一个用例场景,还有许多其他场景,其中一些在BCL中。IEnumerable<T>这是一个不错的选择,它由诸如ICollection<T>和IList<T>所实现,又由诸如Array和的具体类型实现List<T>。它是使许多您可能习惯使用的编程结构的接口,例如LINQ。LINQ不在乎该类的实际实现*,它只是希望能够枚举它并执行适当的过滤和/或投影。
IDisposable是另一个很好的BCL示例。您想知道一个类需要自己清除。它具体需要清除的内容留给该类,但是根据其实现的性质IDisposable,您知道它需要自行清除,因此最好将其用法包装在一个using语句中,或者手动确保.Dispose一旦已经完成了该对象的工作。
* LINQ实际上确实对某些接口进行了优化。