这是有些后续问题至此 的问题.

假设我有一个继承树如下:

Car -> Ford -> Mustang -> MustangGT

是有益的接口定义 这些课程?例如:

ICar -> IFord -> IMustang -> IMustangGT

我可以看到,也许其他类(喜欢 Chevy)想要实现 IcarIFord 甚至可能 IMustang, 但可能不是 IMustangGT 因为它是如此具体。是的接口多余的,在这种情况下?

此外,我将认为任何一类就要实现 IFord 肯定会想使用其一个继承通过继承 Ford 所以不要重复代码。如果这是一个给定,什么是有益的也行 IFord?

有帮助吗?

解决方案

根据我的经验,当你有几个类需要响应相同的方法或方法时,最好使用接口,以便它们可以被其他代码互换使用,这些代码将针对这些类的通用接口编写。接口的最佳用途是协议很重要,但每个类的底层逻辑可能不同。如果您原本会复制逻辑,请考虑使用抽象类或标准类继承。

在回答问题的第一部分时,我建议不要为每个类创建一个界面。这会不必要地混乱你的类结构。如果您发现需要界面,可以随时添加。希望这有帮助!

亚当

其他提示

我同意 adamalex的回复,应该由应该响应的类共享接口某些方法。

如果类具有相似的功能,但在祖先关系中没有直接相关,那么接口将是将该功能添加到类而不在两者之间复制功能的好方法。 (或者有多个实现只有细微差别。)

虽然我们正在使用汽车类比,一个具体的例子。假设我们有以下类:

Car -> Ford   -> Escape  -> EscapeHybrid
Car -> Toyota -> Corolla -> CorollaHybrid

汽车有 wheels ,可以 Drive() Steer()。所以这些方法应该存在于 Car 类中。 (可能 Car 类将是一个抽象类。)

沿着这条线走下去,我们区分了 Ford Toyota (可能是因为车上标志类型的差异,也可能是一个抽象类。 )

然后,最后我们有一个 Escape Corolla 类,它们是完全实现为汽车的类。

现在,我们如何制作 Hybrid 车辆?

我们可以有一个 Escape 的子类,它是 EscapeHybrid ,它添加了 FordsHybridDrive()方法,以及 Corolla的子类 CorollaHybrid ToyotasHybridDrive()方法。这些方法基本上都是做同样的事情,但我们有不同的方法。 Yuck。好像我们可以做得更好。

假设混合具有 HybridDrive()方法。由于我们不想最终拥有两种不同类型的混合(在完美的世界中),因此我们可以创建一个 IHybrid 接口,它具有 HybridDrive()方法

所以,如果我们要制作 EscapeHybrid CorollaHybrid ,我们所要做的就是实现<代码> IHybrid 界面

对于一个真实世界的例子,我们来看看Java。可以将对象与另一个对象进行比较的类实现 Comparable 接口。顾名思义,接口应该是可比较的类,因此名称为“Comparable”。

感兴趣的是汽车示例用于 Interfaces 课程中 Java教程

您根本不应该实现任何这些接口。

类继承描述对象 (例如:它的身份)。这很好,但是大多数情况下对象 是什么,远不如对象那么重要。这就是接口的用武之地。

界面应描述对象做什么,或者它的作用。通过这个我的意思是它的行为,以及在给定行为的情况下有意义的操作集。

因此,良好的接口名称通常应为 IDriveable IHasWheels 等形式。有时,描述此行为的最佳方式是引用一个众所周知的其他对象,因此您可以说“行为就像其中一个”。 (例如: IList )但恕我直言,这种命名形式属于少数。

鉴于逻辑,接口继承有意义的场景与对象继承有意义的场景完全不同 - 通常这些场景与彼此都是。

希望能帮助您思考实际需要的接口: - )

我只说为你需要引用的东西制作一个界面。您可能还有其他一些需要了解汽车的类别或功能,但是有多少东西需要了解福特?

不要构建你不需要的东西。如果事实证明你需要接口,那么返回构建它们是一件很小的努力。

另外,在迂腐的一面,我希望你实际上并没有构建看起来像这种层次结构的东西。这不是继承应该用于什么。

只有在需要该级别的功能时才创建它。

重新分解代码始终处于正在进行的过程中。

有些工具可以让您在必要时提取界面。 例如。 http://geekswithblogs.net/ JaySmith /存档/ 2008/2月27日/重构视觉工作室提取物-interface.aspx

制作ICar和其余所有(Make = Ford,Model = Mustang和stuff)作为实现接口的类的成员。

你可能想拥有你的福特课程,例如GM课程,如果你不想沿着检查 Make == Whatever 的路线去实现ICar以便使用多态,那就是符合你的风格。

无论如何 - 在我看来,这些是汽车的属性,而不是相反 - 你只需要一个界面,因为方法很常见:刹车,加速等等。

福特可以做其他车不能做的事吗?我不这么认为。

我会创建前两个级别,ICar和IFord,然后单独留下第二级,直到我需要第二级接口。

仔细考虑您的对象如何在您的问题域中相互交互,并考虑您是否需要具有多个特定抽象概念的实现。使用接口提供围绕其他对象与之交互的概念的契约。

在您的示例中,我建议福特可能是制造商,Mustang是制造商福特使用的ModelName值,因此您可能会更喜欢:

IVehichle - &gt; CarImpl,MotorbikeImpl - 有一个制造商有很多ModelNames

在这回答有关 差之间的接口和类, 我的解释是:

  • 接口暴露了什么概念 (中期的"是什么 "有效的,在编制时间),和被用于 (MyInterface x=...)
  • 类暴露了什么概念 (实际上是在运行时执行),并用于价值观或对象(MyClass x或aMyClass.方法())

所以如果你需要储存成为一个'Ford'变量(这一概念的价值)不同的亚类的福特,创建一个IFord.否则,不麻烦直到你真正需要它。

这是一个标准:如果它不能满足,IFord可能是无用的。
如果这是满足,那么其他条件暴露在先前的答案适用于:如果福特的具有丰富的API比汽车,IFord是有用的多态性的目的。如果不是,国际资产追回中心是不够的。

在我看来,界面是一种工具,可以强制要求一个类实现某个特征,或者(我喜欢这么认为)一个特定的“行为”。对我来说,我认为如果我的onterface开头的大写字母命名为人称代词,我试着命名我的界面,这样他们就可以这样读... ICanFly,IKnowHowToPersistMyself IAmDisplayable等...所以在你的例子中,我不会创建一个接口来镜像任何特定类的完整公共签名。我会分析公共签名(行为),然后将成员分成更小的逻辑组(越小越好),如(使用你的例子)IMove,IUseFuel,ICarryPassengers,ISteerable,IAccelerate,IDepreciate等......然后申请那些与我系统中其他类相关的接口需要它们

一般来说,考虑这个问题的最佳方式(以及OO中的许多问题)是考虑合同的概念。

合同被定义为两个(或多个)当事方之间的协议,规定了各方必须履行的具体义务;在程序中,这是一个类将提供的服务,以及为了获得服务而必须提供的类。接口声明了实现接口的任何类必须满足的契约。

考虑到这一点,您的问题在某种程度上取决于您使用的语言和您想要做的事情。

经过多年的OO(比如,天啊,30年),我通常会为每个合同编写一个接口,特别是在Java中,因为它使测试变得如此简单:如果我有一个类的接口,我几乎可以轻松地构建模拟对象。

接口旨在成为通用公共API,用户将被限制使用此公共API。除非您打算使用 IMustangGT 的类型特定方法,否则您可能希望将接口层次结构限制为 ICar IExpensiveCar

仅从Interfaces和抽象类继承。

如果您有几个几乎相同的类,并且您需要实现大多数方法,请使用和Interface结合购买其他对象。 点击 如果Mustang类如此不同,那么不仅要创建一个接口ICar,还要创建IMustang 因此,福特和野马等级可以从ICar IMustang继承ICar,Mustang和MustangGT。

如果您实施福特班并且方法与野马相同,请从野马购买:

class Ford{
  public function Foo(){
    ...
    Mustang mustang  = new Mustang();
    return mustang.Foo();
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top