接口:简化
本文关键字:简化 接口 | 更新日期: 2023-09-27 18:28:46
我一直在做一些关于接口的研究,以及一个简单的外行对它真正含义的解释。当在浩瀚的书籍中搜索时,出于某种原因,人们喜欢使用过于复杂的解释和行话来解释真正简单的概念(我想这会让它们感觉很大),我有一种直觉,在这种情况下也是如此。
因此,据我所知,接口似乎只不过是保留方法名称、返回类型(如果有的话)以及它们接受的参数的类型和数量的一种方式。因此,当一个类实现一个(或多个)接口时,它必须从接口中定义每个方法的主体。我是被这个弄得鼻青脸肿还是需要继续挖?
附言:我知道javascript不支持接口,但我仍然需要理解这个概念,因为在很多地方都展示了如何在一定程度上进行模拟。
出于某种原因,人们喜欢使用过于复杂的解释和行话来解释真正简单的概念(猜测这会让他们感觉自己很棒)
考虑避开那些将不良动机归咎于试图帮助你的人的编辑评论试图让别人帮助你的方式真的很糟糕
接口似乎只不过是保留方法名称、返回类型(如果有的话)以及所需参数的类型和数量的一种方式。因此,当一个类实现一个或多个接口时,它必须从接口中定义每个方法的主体。我是被这个弄得鼻青脸肿还是需要继续挖?
你走在正确的轨道上,但你在细节上犯了错误。例如,在C#中,实现类不需要来提供主体。例如,与接口方法相对应的方法可以是抽象类中的抽象方法,而抽象类则没有主体。在C#中,接口可能需要方法以外的成员;属性、事件和索引器。
一种更简洁、更典型的方式来表达接口强加要求,而类型提供与特定签名匹配的成员的想法,就是说接口表示合同必须由其实现者履行。但这可能太复杂了,对你的肠胃来说太不舒服了。
我用大多数人都理解的比喻——塑料成型——向外行解释这个概念。
界面以与模具提供成品形状完全相同的方式定义对象的形状。
你可以用白色塑料,蓝色塑料,像环氧树脂或粘土之类的异国情调的东西来注射模具。
重要的是,无论它们实际上是由什么制成的,它们都具有与产品购买者完全一致的形状。
对于代码来说,这意味着无论使用什么代码来实现接口,它们对最终用户都遵循相同的一致合同/形状。
我希望这能有所帮助。
编辑-
为了将类比扩展到抽象类,想象一下成型过程中的下一步。你经营着白色、蓝色和红色的塑料生产,但每件物品都需要在单独的工厂喷漆,我们只是把它们运出去。
项目尚未完成,但已定义其形状。稍后会有人来填写我们工厂留下的空白。
这些物品只有在完成最后一道油漆工序后才能出售。
在代码中,接口的抽象实现提供了一些(或没有)实现,但留下另一个子类来完成约定,同样,在约定完成之前,没有人可以创建该类的实例。
不过,以同样的方式,你仍然可以在代码中引用抽象类,就像你可以将未上漆的模具项目称为"白色模制的东西"——不管它是否上漆!
编辑2
以下是的一个简短示例
void Main()
{
//IMold mold = new IMold(); // error - can't create instance of an interface
//Fruit fruit = new Fruit(); // error - can't create instance of an abstract class
Apple apple1 = new Apple(); // good
Orange orange1 = new Orange(); // good
Fruit apple2 = (Fruit)apple1; // good - Apples are fruit
Fruit orange2 = (Fruit)orange1; // good - oranges are fruit
IFruitMold apple3 = (IFruitMold)apple2; // good - Apples fit the Mold
IFruitMold orange3 = (IFruitMold)orange2; // good - Oranges also fit the mold
//now I can do this:
//Notice that `fruits` is of type IList<T> but the new is List<T>
//This is the exact concept we are talking about
//IList<T> is some kind of set of items that can be added or subtracted from
//but we don't have to care about the implementation details of *HOW* this is done
IList<IFruitMold> fruits = new List<IFruitMold>();
fruits.add(apple3);
fruits.add(orange3);
foreach( var fruit in fruits )
{
fruit.PlasticColor.Dump(); // ok I can read
fruit.PlasticColor = ""; // error - no Set defined in the interface
// depending on the **implementation details** of what type of fruit this is true or false
// we don't care in the slightest, we just care that we have some IFruitMold instances
fruit.RequiresPainting.Dump();
}
}
interface IFruitMold
{
string PlasticColor { get; }
bool RequiresPainting { get; }
}
abstract class Fruit : IFruitMold
{
private string m_PlasticColor = string.Empty;
public string PlasticColor { get; private set; }
public abstract bool RequiresPainting { get; }
}
//notice that we only define the abstract portion of the base class
//it defined PlasticColor for us already!
//the keyword `override` is required - it is to make it clear that
//this member is overriding a member from it's parent.
class Apple : Fruit
{
public override bool RequiresPainting { get { return true; } }
}
class Orange : Fruit
{
public override bool RequiresPainting { get { return false; } }
}
是的,简而言之,接口是用来声明并向其他人承诺类将具有某些方法的。
当您创建通用方法和函数时,这是很好的,因为您需要更抽象的设计。您只想知道您的函数可以接收一个具有方法A、B和C的对象。
接口只是一个简单的空类,它显示了真实类的外观。我想你的概念还可以。
它们不保留任何东西(我不明白你的意思),只是一种方式,当你围绕接口构建你的类时,你事先就知道你的类会是什么样子。而且你也可以在之前知道它会有哪些方法。
当一个类实现一个(或多个)接口时,它必须定义接口中每个方法的主体。
是的。接口是合同。它们让其他人知道您的类实现了某些功能。
我认为这不仅仅是保留方法名称,它是一种签订合同的方式,即方法将存在,调用者不需要知道它做了什么,但它仍然可以被称为
一个很好的例子是,钢笔和铅笔都可以用write方法实现Iwriter接口,但无论谁调用write方法,都不需要知道其中一个使用墨水,另一个使用铅,调用者只需要知道它将在纸上写单词。
接口提供了与一组对象交互的统一方式。
不管对象是什么,如果它实现了接口,我们知道它将响应接口中定义的方法。通过这种方式,我们可以创建表示项目中不同事物的对象,并且仍然以相同的方式与它们交互。接口中定义的方法的实际实现可能完全不同,但它们将采用相同的输入并提供相同类型的输出。
基本上,接口是一个可以定义属性(getter和setter)或方法(使用您需要的任何参数)的契约。如果一个对象"实现"了接口,它需要为接口中定义的所有属性和方法定义一个具体的实现。
对于单元测试或控制反转容器,接口真的是自带的,因为你可以在不了解实际实现它的对象的情况下调用接口上的方法/属性。
接口用于在一组完全不相关的对象之间提供通用功能。
比方说,我们有一堆动物物体,我们需要把宠物和那堆分开。如果我们强制执行一个合同,使得所有作为宠物的动物都需要实现IPet
接口,那么分离的任务就变得非常简单。