在我的开发学习中,我觉得我必须学习更多关于接口的知识。
我经常读到它们,但我似乎无法理解它们。
我读过这样的例子:动物基类,IAnimal接口的东西,如“Walk”,“Run”,“GetLegs”等-但我从来没有工作过,觉得“嘿,我应该在这里使用接口!”
我错过了什么?为什么这个概念对我来说这么难理解!我只是害怕这样一个事实,我可能从来没有意识到一个具体的需要-主要是由于一些缺失的理解他们!这让我觉得我作为一名开发人员缺少了一些东西!如果有人有过这样的经历,并取得了突破,我会很感激一些关于如何理解这个概念的建议。谢谢你!
I like Jimmy's answer a lot, but I feel I need to add something to it. The key to the whole thing is the "able" in IProcessable . It indicates a capability (or property, but meaning "intrinsic quality", not in the sense of C# properties) of the object that implements the interface. IAnimal is probably not a good example for an interface, but IWalkable might be a good interface to have if your system has many things that can walk. You might have classes derived from Animal such as Dog, Cow, Fish, Snake. The first two would probably implement IWalkable, the latter two don't walk, so they wouldn't. Now you ask "why not just have another superclass, WalkingAnimal, that Dog and Cow derive from?". The answer is when you have something completely outside the inheritance tree that also can walk, such as a robot. Robot would implement IWalkable, but probably wouldn't derive from Animal. If you want a list of things that can walk, you type it as IWalkable and you can put all walking animals plus robots in the list.
现在,将IWalkable替换为IPersistable这样更像软件的东西,这样的类比就更接近你在实际程序中看到的情况了。
In my experience the driving force to create interfaces didn't occur until I start doing unit testing with a mocking framework. It became abundantly clear that using interfaces was going to make mocking much easier (since the framework depended on the methods being virtual). Once I started I saw the value of abstracting away the interface to my class from the implementation. Even if I don't create an actual interface, I try now to make my methods virtual (providing an implicit interface that can be overridden).
我发现还有许多其他原因可以加强重构到接口的良好实践,但是单元测试/模拟的事情提供了最初的“顿悟时刻”的实践经验。
EDIT: To clarify, with unit testing and mocking I always have two implementations -- the real, concrete implementation and an alternate mock implementation used in testing. Once you have two implementations, the value of the interface becomes obvious -- deal with it in terms of the interface so you can replace the implementation at any time. In this case I'm replacing it with a mock interface. I know that I can do this without an actual interface if my class is constructed properly, but using an actual interface reinforces this and makes it cleaner (clearer to the reader). Without this impetus, I don't think I would have appreciated the value of interfaces since most of my classes only, ever have a single concrete implementation.
假设你想要模拟当你试图睡觉时可能发生的烦恼。
接口前的模型
class Mosquito {
void flyAroundYourHead(){}
}
class Neighbour{
void startScreaming(){}
}
class LampJustOutsideYourWindow(){
void shineJustThroughYourWindow() {}
}
正如你清楚地看到的,当你试图睡觉时,许多“事情”都可能令人讨厌。
使用没有接口的类
但是在使用这些类时,我们遇到了一个问题。他们毫无共同之处。您必须分别调用每个方法。
class TestAnnoyingThings{
void testAnnoyingThinks(Mosquito mosquito, Neighbour neighbour, LampJustOutsideYourWindow lamp){
if(mosquito != null){
mosquito.flyAroundYourHead();
}
if(neighbour!= null){
neighbour.startScreaming();
}
if(lamp!= null){
lamp.shineJustThroughYourWindow();
}
}
}
带有接口的模型
为了克服这个问题,我们可以引入一个iterface
interface Annoying{
public void annoy();
}
并在类中实现它
class Mosquito implements Annoying {
void flyAroundYourHead(){}
void annoy(){
flyAroundYourHead();
}
}
class Neighbour implements Annoying{
void startScreaming(){}
void annoy(){
startScreaming();
}
}
class LampJustOutsideYourWindow implements Annoying{
void shineJustThroughYourWindow() {}
void annoy(){
shineJustThroughYourWindow();
}
}
接口使用
这将使这些类的使用更容易
class TestAnnoyingThings{
void testAnnoyingThinks(Annoying annoying){
annoying.annoy();
}
}
使用接口有很多目的。
Use in polymorphic behavior. Where you want to call specific methods of a child class with an inteface having a reference to the child class.
Having a contract with classes to implement all of the methods where it is necessary, like most common use is with COM objects , where a wrapper class is generated on a DLL which inherits the interface; these methods are called behind the scenes, and you just need to implement them but with the same structure as defined in the COM DLL which you can only know through the interface that they expose.
To reduce memory usage by loading specific methods in a class. Like if you have three business objects and they are implemented in a single class, you can use three interfaces.
例如IUser, IOrder, IOrderItem
public interface IUser()
{
void AddUser(string name ,string fname);
}
// Same for IOrder and IOrderItem
//
public class BusinessLayer: IUser, IOrder, IOrderItem
{
public void AddUser(string name ,string fname)
{
// Do stuffs here.
}
// All methods from all interfaces must be implemented.
}
如果你只想添加一个用户,可以这样做:
IUser user = new (IUser)BusinessLayer();
// It will load all methods into memory which are declared in the IUser interface.
user.AddUser();