可能有人请神秘性接口为我或点我一些很好的例子吗? 我一直在这里和那里看到接口弹出,但我还没有曾经真正接触到的接口或何时使用它们很好的解释。
我说的是在接口和抽象类的上下文接口。
可能有人请神秘性接口为我或点我一些很好的例子吗? 我一直在这里和那里看到接口弹出,但我还没有曾经真正接触到的接口或何时使用它们很好的解释。
我说的是在接口和抽象类的上下文接口。
接口允许您编写针对“说明”,而不是一个类型,它可以让你的软件的更松散关联的元素。
想想这样说:你要与某人在立方体你旁边共享数据,所以你拿出你的闪存盘和复制/粘贴。 你走进隔壁的家伙说:“是USB?” 和你说的是 - 所有的设置。 没关系的闪存盘的大小,也不是生产商 - 所有重要的是,它的USB接口。
以同样的方式,接口允许您generisize开发。 用另一个比喻 - 想像你想创建,几乎画汽车的应用程序。 你可能有这样的签名:
public void Paint(Car car, System.Drawing.Color color)...
这会工作,直到你的客户说:“现在我要画卡车”,所以你可以这样做:
public void Paint (Vehicle vehicle, System.Drawing.Color color)...
这将扩大您的应用程序......直到你的客户说:“现在我要画的房子!” 你可能已经从一开始做的是创建一个接口:
public interface IPaintable{
void Paint(System.Drawing.Color color);
}
...并通过了对你的日常:
public void Paint(IPaintable item, System.Drawing.Color color){
item.Paint(color);
}
希望这是有道理的 - 这是一个非常简单的说明,但希望得到于它的心脏。
接口建立一个类,并调用它的代码之间的合同。 他们还让你有实现相同的接口,但做不同的动作或事件,而不必知道你实际工作与类似的类。 这可能更有意义,作为一个例子,所以让我尝试一个在这里。
假设你有一个名为狗,猫,和鼠标一对夫妇类。 这些类是宠物在理论上可以继承他们都来自所谓的宠物另一个类,但这里的问题。 宠物本身并没有做任何事情。 你不能去商店,买了宠物。 你可以去购买狗或猫,但宠物是一个抽象的概念,而不是具体的。
所以,你知道宠物可以做某些事情。 他们可以睡,或吃等,所以你定义一个名为IPET一个接口,它看起来像这样(C#语法)
public interface IPet
{
void Eat(object food);
void Sleep(int duration);
}
每次你的狗,猫,和鼠标类实现IPET。
public class Dog : IPet
所以,现在每个这些类中必须有它自己的执行吃饭和睡觉的。 耶你有一个合同...现在什么意义。
接下来,让我们说,你要创建一个名为PetStore的新对象。 这是不是一个很好的PetStore所以他们基本上只是卖给你一个随机宠物(是的,我知道这是一个人为的例子)。
public class PetStore
{
public static IPet GetRandomPet()
{
//Code to return a random Dog, Cat, or Mouse
}
}
IPet myNewRandomPet = PetStore.GetRandomPet();
myNewRandomPet.Sleep(10);
问题是你不知道它是什么类型的宠物。 由于界面虽然你知道叫什么,它都将吃和睡。
所以,这个答案可能没有帮助的,不过在总的想法是,接口让你不喜欢依赖注入和控制反转整洁的东西,在那里你可以得到一个对象,有反对而没有真正能做到的东西明确定义的列表知道具体类型的对象是什么。
最简单的答案是,接口定义你的类可以做。 这是一个“合同”,指出你的类就能够做到这一点的动作。
Public Interface IRollOver
Sub RollOver()
End Interface
Public Class Dog Implements IRollOver
Public Sub RollOver() Implements IRollOver.RollOver
Console.WriteLine("Rolling Over!")
End Sub
End Class
Public Sub Main()
Dim d as New Dog()
Dim ro as IRollOver = TryCast(d, IRollOver)
If ro isNot Nothing Then
ro.RollOver()
End If
End Sub
基本上,你可以保证在狗类总是有,只要它继续实现该接口翻身的能力。 如果猫曾经获得能力侧翻(),他们也可以实现该接口,并要求他们侧翻时,你可以把狗和猫均匀()。
当你驾驶一辆朋友的车,你或多或少知道该怎么做。 这是因为传统汽车都有着非常相似的界面:方向盘,踏板,等等。 觉得这个接口作为汽车制造商和车手之间的合同。 由于(在软件方面的接口的用户/客户端)驱动程序,你不需要学习不同的车的细节,以便能够驱动它们:例如,所有你需要知道的是,转动方向盘使汽车转弯。 作为一个汽车制造商(该接口的实现在软件方面的供应商),你有一个明确的想法你的新车应以及应如何表现让驾驶者可以使用它们没有太多额外的训练。 该合同是什么人在软件设计是指为解耦(用户从提供者) - 客户端代码是使用一个接口,而不是其具体的实现方面,因此并不需要知道物体的细节实现该接口。
接口是减少的系统的不同的,可能不同的零件之间耦合的机制。
从.NET的角度
当你创建一个实现接口的类,你必须提供一个显式或隐式执行接口定义的所有方法和属性。
此外,.NET仅具有单继承,和接口是一个对象,以露出的方法来是不知道的,或躺下它的类层次结构之外的其它对象的必要条件。 这也被称为暴露行为。
考虑的是我们有很多DTO的(数据传输对象)对谁最后更新的属性,当是如此。 问题是,不是所有的DTO的这个属性,因为它并不总是相关的。
同时,我们希望有一个通用的机制,以保证如果有交房时的工作流程设置了这些属性,但工作流程对象应该从提交的对象是松耦合。 即提交工作流程方法不应该真正了解每个对象的所有细微之处,并在工作流程中的所有对象不一定是DTO对象。
// First pass - not maintainable
void SubmitToWorkflow(object o, User u)
{
if (o is StreetMap)
{
var map = (StreetMap)o;
map.LastUpdated = DateTime.UtcNow;
map.UpdatedByUser = u.UserID;
}
else if (o is Person)
{
var person = (Person)o;
person.LastUpdated = DateTime.Now; // Whoops .. should be UtcNow
person.UpdatedByUser = u.UserID;
}
// Whoa - very unmaintainable.
在上面的代码中, SubmitToWorkflow()
必须知道每个对象。 此外,该代码是一个庞大的if / else /开关一塌糊涂,违反不要重复自己 (DRY)的原则,并要求开发商要记住复制/粘贴变化,每一个新的对象被添加到系统的时间。
// Second pass - brittle
void SubmitToWorkflow(object o, User u)
{
if (o is DTOBase)
{
DTOBase dto = (DTOBase)o;
dto.LastUpdated = DateTime.UtcNow;
dto.UpdatedByUser = u.UserID;
}
这是稍微好一点,但它仍然很脆弱。 如果我们要提交其他类型的对象,我们需要还需要更多的case语句。 等等
// Third pass pass - also brittle
void SubmitToWorkflow(DTOBase dto, User u)
{
dto.LastUpdated = DateTime.UtcNow;
dto.UpdatedByUser = u.UserID;
它仍然很脆弱,而且这两种方法强制所有的DTO必须实现这个属性,我们表示不普遍适用的约束。 有些开发者会想写什么也不做的方法,但味道不好。 我们不希望班假装他们支持更新的跟踪,但没有。
如果我们定义了一个非常简单的接口:
public interface IUpdateTracked
{
DateTime LastUpdated { get; set; }
int UpdatedByUser { get; set; }
}
任何类需要这种自动更新跟踪可以实现该接口。
public class SomeDTO : IUpdateTracked
{
// IUpdateTracked implementation as well as other methods for SomeDTO
}
可以进行的工作流程方法是很多更通用,更小,更易于维护,而且将继续无论多少类是如何实现的接口(DTO的或其他方式),因为它仅与接口处理工作。
void SubmitToWorkflow(object o, User u)
{
IUpdateTracked updateTracked = o as IUpdateTracked;
if (updateTracked != null)
{
updateTracked.LastUpdated = DateTime.UtcNow;
updateTracked.UpdatedByUser = u.UserID;
}
// ...
void SubmitToWorkflow(IUpdateTracked updateTracked, User u)
将保证类型安全,但它似乎并没有在这种情况下的相关性。 在我们使用的一些生产代码,我们必须代码生成从数据库中定义创建这些DTO类。 开发人员做的唯一的事情就是要正确地创建字段名称和与接口装饰类。 只要属性称为LASTUPDATED和UpdatedByUser,它只是工作。
也许你问如果我的数据库是遗产,那是不可能的,会发生什么? 你只需做一些更多的输入; 接口另一大特点是,他们可以让你创建的类之间的桥梁。
在下面的代码,我们有一个虚构的LegacyDTO
,具有类似命名的字段预先存在的对象。 它实现IUpdateTracked接口弥合现有的,但不同的命名属性。
// Using an interface to bridge properties
public class LegacyDTO : IUpdateTracked
{
public int LegacyUserID { get; set; }
public DateTime LastSaved { get; set; }
public int UpdatedByUser
{
get { return LegacyUserID; }
set { LegacyUserID = value; }
}
public DateTime LastUpdated
{
get { return LastSaved; }
set { LastSaved = value; }
}
}
你可能一点酷,但不是混乱有多个属性? 或者,如果已经有这些属性,但它们的意思是别的东西会发生什么? .NET给你明确地实现接口的能力。
这意味着,当我们使用到IUpdateTracked参考的IUpdateTracked属性才可以看到。 注意如何没有对声明没有公开改性剂,并声明包含接口名称。
// Explicit implementation of an interface
public class YetAnotherObject : IUpdatable
{
int IUpdatable.UpdatedByUser
{ ... }
DateTime IUpdatable.LastUpdated
{ ... }
有这么多的灵活性定义类是如何实现的接口给开发人员很大的自由,从消耗它的方法分离的对象。 接口是打破耦合的好方法。
还有很多更不仅仅是这个接口。 这只是利用基于接口的编程的一个方面的简化真实的例子。
正如我前面提到的,和其他反应,可以创建采取的方法和/或返回接口引用,而不是特定的类引用。 如果我需要找到重复的名单,我可以写需要和返回的方法IList
,我并不受限于具体的集合类(定义,关于名单的工作操作的接口)。
// Decouples the caller and the code as both
// operate only on IList, and are free to swap
// out the concrete collection.
public IList<T> FindDuplicates( IList<T> list )
{
var duplicates = new List<T>()
// TODO - write some code to detect duplicate items
return duplicates;
}
如果它是一个公共接口,你宣布我保证接口×看起来像这样! 一旦你已经出厂编号,并出版了接口,你永远不应该改变它。 只要消费者代码开始依靠该接口上的,你不想要打破他们的代码在现场。
见这Haacked后有一个良好的讨论。
抽象类能,而接口不能提供实施。 抽象类是在某些方面在版本方面更加灵活,如果你遵循喜欢NVPI(非虚拟公共接口)模式的一些准则。
这是值得重申的是在.NET中,一个类只能从一个类继承,但它喜欢一个类可以实现多个接口。
接口和依赖注入(DI)的简单总结是,使用的接口使开发人员能够编写抵抗的接口来提供服务编程代码。 在实践中,你可以结束了很多小的接口和小班,和一个想法是,小班做一两件事,只有一件事更容易编写和维护。
class AnnualRaiseAdjuster
: ISalaryAdjuster
{
AnnualRaiseAdjuster(IPayGradeDetermination payGradeDetermination) { ... }
void AdjustSalary(Staff s)
{
var payGrade = payGradeDetermination.Determine(s);
s.Salary = s.Salary * 1.01 + payGrade.Bonus;
}
}
简单地说,在上面的代码片段显示的好处是,薪酬等级确定刚刚注入的年度加薪调整。 薪酬等级是如何确定的实际上并不重要此类。 测试时,显影剂可以模拟薪酬等级判定的结果,以确保所期望的薪水调节功能。 该测试也快,因为测试只是测试类,而不是一切。
这不是一个DI底,虽然因为有整本书专门的主题; 上面的例子是非常简单。
This is a rather "long" subject, but let me try to put it simple.
An interface is -as "they name it"- a Contract. But forget about that word.
The best way to understand them is through some sort of pseudo-code example. That's how I understood them long time ago.
Suppose you have an app that processes Messages. A Message contains some stuff, like a subject, a text, etc.
So you write your MessageController to read a database, and extract messages. It's very nice until you suddenly hear that Faxes will be also implemented soon. So you will now have to read "Faxes" and process them as messages!
This could easily turn into a Spagetti code. So what you do instead of having a MessageController than controls "Messages" only, you make it able to work with an interface called IMessage (the I is just common usage, but not required).
Your IMessage interface, contains some basic data you need to make sure that you're able to process the Message as such.
So when you create your EMail, Fax, PhoneCall classes, you make them Implement the Interface called IMessage.
So in your MessageController, you can have a method called like this:
private void ProcessMessage(IMessage oneMessage)
{
DoSomething();
}
If you had not used Interfaces, you'd have to have:
private void ProcessEmail(Email someEmail);
private void ProcessFax(Fax someFax);
etc.
So, by using a common interface, you just made sure that the ProcessMessage method will be able to work with it, no matter if it was a Fax, an Email a PhoneCall, etc.
Why or how?
Because the interface is a contract that specifies some things you must adhere (or implement) in order to be able to use it. Think of it as a badge. If your object "Fax" doesn't have the IMessage interface, then your ProcessMessage method wouldn't be able to work with that, it will give you an invalid type, because you're passing a Fax to a method that expects an IMessage object.
Do you see the point?
Think of the interface as a "subset" of methods and properties that you will have available, despite the real object type. If the original object (Fax, Email, PhoneCall, etc) implements that interface, you can safety pass it across methods that need that Interface.
There's more magic hidden in there, you can CAST the interfaces back to their original objects:
Fax myFax = (Fax)SomeIMessageThatIReceive;
The ArrayList() in .NET 1.1 had a nice interface called IList. If you had an IList (very "generic") you could transform it into an ArrayList:
ArrayList ar = (ArrayList)SomeIList;
And there are thousands of samples out there in the wild.
Interfaces like ISortable, IComparable, etc., define the methods and properties you must implement in your class in order to achieve that functionality.
To expand our sample, you could have a List<> of Emails, Fax, PhoneCall, all in the same List, if the Type is IMessage, but you couldn't have them all together if the objects were simply Email, Fax, etc.
If you wanted to sort (or enumerate for example) your objects, you'd need them to implement the corresponding interface. In the .NET sample, if you have a list of "Fax" objects and want to be able to sort them by using MyList.Sort(), you need to make your fax class like this:
public class Fax : ISorteable
{
//implement the ISorteable stuff here.
}
I hope this gives you a hint. Other users will possibly post other good examples. Good luck! and Embrace the power of INterfaces.
warning: Not everything is good about interfaces, there are some issues with them, OOP purists will start a war on this. I shall remain aside. One drawback of an Interfce (in .NET 2.0 at least) is that you cannot have PRIVATE members, or protected, it must be public. This makes some sense, but sometimes you wish you could simply declare stuff as private or protected.
除了功能接口具有编程语言中,他们也表达设计理念给其他人时,是一个强大的语义工具。
精心设计的接口,一个代码库是一下子轻松了许多讨论。 “是的,你需要一个CredentialsManager注册新的远程服务器。” “传递一个属性映射到ThingFactory获得一个工作实例。”
能够解决与一个字一个复杂的东西是非常有用的。
接口让你在一个通用的方式编写物体打击。 例如,假设你有一个发出报告的方法。 现在,假设你有来在您需要编写一个新的报告的新要求。 这将是很好,如果你可以重用你已经写了正确的方法是什么? 接口使得那么容易:
interface IReport
{
string RenderReport();
}
class MyNewReport : IReport
{
public string RenderReport()
{
return "Hello World Report!";
}
}
class AnotherReport : IReport
{
public string RenderReport()
{
return "Another Report!";
}
}
//This class can process any report that implements IReport!
class ReportEmailer()
{
public void EmailReport(IReport report)
{
Email(report.RenderReport());
}
}
class MyApp()
{
void Main()
{
//create specific "MyNewReport" report using interface
IReport newReport = new MyNewReport();
//create specific "AnotherReport" report using interface
IReport anotherReport = new AnotherReport();
ReportEmailer reportEmailer = new ReportEmailer();
//emailer expects interface
reportEmailer.EmailReport(newReport);
reportEmailer.EmailReport(anotherReport);
}
}
接口方面也很关键多态性的“OOD三大支柱”之一。
有些人提到了上面,多态仅仅意味着一个给定的类可以采取不同的“形式”。 也就是说,如果我们有两个班,“狗”和“猫”,并都实现了接口“INeedFreshFoodAndWater”(嘻嘻) - 你的代码可以做这样的事情(伪):
INeedFreshFoodAndWater[] array = new INeedFreshFoodAndWater[];
array.Add(new Dog());
array.Add(new Cat());
foreach(INeedFreshFoodAndWater item in array)
{
item.Feed();
item.Water();
}
这是强大的,因为它允许你将不同类的抽象对象,并允许你做这样的事情让你的对象更加松散耦合,等等。
好了,所以它是关于抽象类与接口...
从概念上讲,抽象类在那里被用作基类。 很多时候,他们本身已经提供了一些基本的功能,而子类必须提供自己的实现的抽象方法(这些是未在抽象基类实现的方法)。
接口主要用于从特定的实现细节解耦客户端代码。 此外,有时切换实现在不改变客户端代码的能力使得客户端代码更通用。
在技术层面上,它很难画出抽象类和接口之间的界限,因为某些语言(如C ++),没有语法差,还是因为你也可以使用抽象类的去耦或推广的目的。 使用抽象类作为接口是可能的,因为每一个基类,顾名思义,定义了它的所有子类中应履行的接口(即,它应该是可以使用一个子类,而不是一个基类)。
接口是执行该一个对象实现一定量的功能性,而无需使用继承(这会导致强耦合代码,代替松散耦合这可以通过使用接口来实现)的方法。
接口描述的功能,而不是实现。
大多数你遇到的接口是方法和属性特征的集合。 任何一个谁实现的接口必须对什么都在界面中提供的定义。
简单地说:一个接口是方法定义的一类,但他们没有实现。 相反一个抽象类有一些实现的方法,但不是全部。
想想接口作为合同的。 当一个类实现一个接口,它基本上同意履行该合同的条款。 作为消费者,你只在乎你有对象可以履行自己的合同义务。 他们的内部运作和细节并不重要。
一个很好的理由使用的界面与Java中的抽象类是子类不能扩展多个基类,但可以实现多个接口。
Java不允许多重继承(有很好的理由,查找可怕的钻石),但如果你希望你的级供应几套的行为? 你说你想要的人谁使用它知道它可以被序列化,而且它可以在屏幕上画自己。 答案是实现两个不同的接口。
由于接口包含没有实现自己并没有实例成员是安全的实现几个人在没有歧义同一类。
不利的一面是,你将不得不单独在每个类的实现。 所以,如果您的层次结构很简单,有一些应该是所有的继承类使用抽象类相同的执行部分。
假设你指的是在接口静态类型的面向对象语言,主要用途是在声称你的类遵循特定的合同或协议。
假设你有:
public interface ICommand
{
void Execute();
}
public class PrintSomething : ICommand
{
OutputStream Stream { get; set; }
String Content {get; set;}
void Execute()
{
Stream.Write(content);
}
}
现在你有一个替代的指挥结构。 实现IExecute可以被存储在某种类型的列表类的任何实例,说一些实现IEnumerable,你可以通过该循环并执行每一个,知道每个对象将只是做正确的事情。 您可以通过实现CompositeCommand这将有自己的命令列表运行,或LoopingCommand重复运行一组命令创建一个复合的命令,那么你就会有最简单的解释的。
当你可以减少一组对象的行为,他们都在共同拥有,你可能有导致提取的接口。 此外,有时你可以使用接口来防止物体从那个类的顾虑不慎侵入; 例如,你可以实现一个接口,只允许客户端检索,而不是在你的对象变化数据,并有大多数对象只接收到检索界面的参考。
接口最好的工作时,你的界面相对简单,做一些假设。
中查找Liskov的subsitution原则,使更多的这种意义。
像C ++的一些静态类型语言不支持接口,一流的理念,让您创建一个使用纯抽象类的接口。
更新既然你似乎询问抽象类与接口,这里是我的首选过于简单化:
通常情况下,我做了一个提取接口重构之前,我建立一个抽象类。 我更倾向于建立一个抽象类,如果我觉得应该有一个造物合同(具体而言,构造的特定类型应始终由子类支持)。 但是,我很少在C#/ Java的使用“纯”抽象类。 我更可能实现一类含有有意义的行为至少一个方法,并用抽象的方法,以支持该方法称为模板方法。 那么抽象类是一种行为,这是所有具体子类可以利用,而不必重新实现的基本实现。
答案很简单:一个界面就是一堆方法签名(+返回类型)的。 当一个对象说,它实现了一个接口,你知道它暴露了一套方法。
接口是实现的方式,仍然是强类型和多态规则的一种方法。
一个很好的现实世界的例子是在.NET中IDisposable接口。 实现IDisposable接口的类迫使那个类来实现Dispose()方法。 如果类没有实现的Dispose()你想建立的时候会得到一个编译器错误。 此外,该代码模式:
using (DisposableClass myClass = new DisposableClass())
{
// code goes here
}
将导致myClass.Dispose()时执行退出内部块中自动执行。
然而,这是非常重要的,并没有强制执行,以您的Dispose()方法应该做的事情。 你可以有你的Dispose()方法从文件中随机挑选的食谱并通过电子邮件发送到通讯组列表时,编译器不关心。 IDisposable模式的目的是使资源清理更加容易。 如果一个类的实例将保留文件句柄然后IDisposable接口使得它很容易集中的释放和清理代码在一个地方,并推广使用可确保释放总是发生的风格。
这就是关键接口。 他们简化编程规范和设计模式的一种方式。 其中,只要正确使用,促进了简单,自我记录代码更容易使用,更容易维护,而且更正确。
这是一个分贝相关的例子,我经常使用。 让我们说你有一个对象和容器对象像一个列表。 让我们假设你的某个时候可能需要的对象存储在一个特定的顺序。 假定该序列不相关的阵列中的位置,而是使对象是较大的一组对象和序列位置的一个子集是相关数据库的SQL过滤。
要跟踪您的自定义序列位置的,你可以让你的对象实现自定义的接口。 自定义接口可以调解维持这样的序列所需的组织工作。
例如,你有兴趣的顺序无关,在记录的主键。 随着对象实现了接口,你可以说myObject.next()或myObject.prev()。
你和我找到了“合同”的解释有点混乱我有同样的问题。
如果指定了一个方法接受一个IEnumerable接口为在参数,你可以说这是一个合同指定的参数必须是从IEnumerable接口继承而来,因此一个类型的支持IEnumerable接口指定的所有方法。 但如果我们用一个抽象类或普通类相同的情况是真实的。 从这些类继承的任何对象将确定在传递作为参数。 你会在任何情况下,可以说是继承对象支持在基类中所有公共方法的基类是一个普通的类,抽象类或接口。
与所有的抽象方法的抽象类是基本相同的接口,所以你可以说一个接口只是没有实现的方法的类。 其实你可以从语言下拉界面,只需使用抽象类只有抽象方法来代替。 我认为,我们把它们分开的原因是语义的原因,而是编码的原因,我没有看到的原因,发现它只是混乱。
另一个建议可以重命名接口接口类的接口是一类的另一种变体。
在某些语言中也有它允许一个类继承只有1级,但多个接口而在其他国家,你可以有许多两者的细微的差别,那是另外的问题并没有直接关系,我认为
理解接口最简单的方法是考虑继承意味着什么课开始。 它包括两个方面的内容:
这两项功能是有用的,但因为它是很难让一个类来使用一个以上的类作为自己的,很多语言和框架的成员只允许类从单个基类继承。 在另一方面,与具有一类是可替代多个其他无关的事情没有特别的困难。
此外,由于遗传的第一个益处可以通过封装方法来基本实现,从允许第一类型的多重继承的相对好处是比较有限的。 在另一方面,能够替换的对象为多个不相关类型的东西是其不能没有语言支持容易地实现一个有用的能力。
接口提供通过其语言/框架可以允许程序从继承多个基类型的第二方面获益,而不需要它也提供第一的装置。
接口就像是一个完全抽象类。 也就是说,只有抽象成员的抽象类。 您也可以实现多个接口,就好像从多个完全抽象类继承。 反正..这说明只有帮助,如果你了解一个抽象类是什么。
像其他人在此间表示,接口定义一个合同(如何谁使用该接口将“看”的类)和抽象类定义共享的功能。
让我们来看看代码帮助:
public interface IReport
{
void RenderReport(); // This just defines the method prototype
}
public abstract class Reporter
{
protected void DoSomething()
{
// This method is the same for every class that inherits from this class
}
}
public class ReportViolators : Reporter, IReport
{
public void RenderReport()
{
// Some kind of implementation specific to this class
}
}
public class ClientApp
{
var violatorsReport = new ReportViolators();
// The interface method
violatorsReport.RenderReport();
// The abstract class method
violatorsReport.DoSomething();
}
接口需要实现它们包含在接口定义的方法的任何类。
其目的是使,而不需要看到一个类的代码,你就可以知道它是否可以用于特定的任务。 例如,在Java中,Integer类实现可比的接口,所以,如果你只看到了方法头(公共String类实现可比),你就会知道,它包含的compareTo()方法。
在您简单的情况下,可以实现类似于您使用实现一个共同的基类的接口得到什么东西show()
或者将其定义为抽象的)。 让我改变你的通用名称,以更具体的东西, 鹰 鹰 ,而不是MyClass1的和MyClass2。 在这种情况下,你可以写出这样的代码
Bird bird = GetMeAnInstanceOfABird(someCriteriaForSelectingASpecificKindOfBird);
bird.Fly(Direction.South, Speed.CruisingSpeed);
可以让你写的代码,可以处理任何事情那是一只 鸟 。 然后,你可以写,导致鸟尽自己的事情(飞,吃,产卵,等等),其作用于它把作为鸟的实例代码。 该代码将工作鸟是否真的老鹰 , 鹰 ,或其他任何东西,从鸟派生。
这种格局开始变得混乱,不过,当你没有真正的是一个关系。 假设你想写的是,在天空中飞来飞去的东西代码。 如果你写的代码接受一个鸟的基类,它突然变得难以发展该代码在JumboJet情况下工作,因为当鸟和JumboJet可以肯定两者飞,一个JumboJet肯定不是一只鸟 。
输入接口。
什么鸟 (和老鹰 , 鹰和) 确实有一个共同点,就是他们都可以飞。 如果你写上面的代码,而不是采取行动在接口上,IFLY,该代码可以应用到任何提供该接口的实现。