3

我在这里读了一篇博文:http: //codeofdoom.com/wordpress/2009/02/12/learn-this-when-to-use-an-abstract-class-and-an-interface/

public interface Actor{
   Performance say(Line l);
}
public interface Director{
   Movie direct(boolean goodmovie);
}
public interface ActorDirector extends Actor, Director{
...
}

它说:实际上,有些演员也是导演。如果我们使用接口而不是抽象类。我们可以使用抽象类来实现同样的目的。不幸的是,替代方案需要多达2^n(其中 n 是属性的数量)可能的组合才能支持所有可能性。

问题:为什么抽象类在这里更好?为什么 2^n ?

public abstract class ActorDirector implements Actor,Director{
}
4

4 回答 4

6

您不能从多个类(抽象或非抽象)继承,但可以实现多个接口

如果要创建抽象类,则每个组合都需要一个(n 个属性:2^n 个可能的组合)——以确保每个组合都可以在需要时继承。

如果你使用接口,你只需要定义n个接口(每个属性一个)并根据需要实现它们。

于 2012-04-13T15:35:46.497 回答
1

在决定是否需要Abstract上课时,您需要回答的问题很简单;

实现这些接口中的任何一个的任何类之间共享的任何方法是否有任何通用实现?如果,那么您将把该实现放在一个AbstractClass.

如果不是这样,那么您只需将两者组合成一个Interface,并让所有实现类都提供它们的自定义、非共享实现。

肯定有一个论据要做到这两点。拥有一个允许解决单一继承限制Abstract的超级接口,以及该超级接口的实现,以便为接口中任何方法的任何共享默认实现提供高内聚性。

您获得的错误解决这些问题的经验越多,这些决定就越容易。

于 2012-04-13T15:37:44.707 回答
1

我认为您误解了该帖子:作者并不是说在这种情况下抽象类更好 - 相反,他认为接口更适合。

2^n(或更准确地说2^n-1)而言,这个数字来自于意识到如果你有n正交行为契约,你可以2^n-1从它们中进行非空组合。如果您使用接口将契约添加到实现它们的类中,那么您只需要与行为一样多的接口:用户将能够对他选择实现的行为进行组合,最多2^n-1. 如果您尝试使用抽象类实现同样的灵活性,那么您最终不仅会创建您想要的实现,而且还会创建一直到单个 root 所需的所有中间实现,因为 Java 允许您一次只继承一个类.

于 2012-04-13T15:44:35.237 回答
0

继承分为两部分:

  1. 派生类可以将其父类的公共或受保护方法或字段视为自己的。
  2. 在请求后者的大多数上下文中,派生类型对象可以替代基类型对象。

实现接口的类只能获得后者的好处,但是从抽象类继承的类可以实现两者。另一方面,这个好处带来了一个限制:因为一个类只能将另一个类的方法和字段视为自己的,所以一个类只能从一个抽象类继承。相比之下,一个类可以实现(因此可以替代)任意数量的接口。

不要担心抽象类的组合爆炸。假设一些车辆可以转向(例如 CompactCar),其他车辆可以 AttachFollower(例如铁路机车),而有些车辆可以同时进行(例如 PickupTruck)。aPickupTruck应该可以满足需要能够实现的车辆Steer的代码,以及需要能够执行的车辆的代码AttachFollower。但是,如果SteerAttachFollower都是抽象类,则无法声明PickupTruck一个实例可以执行这两种功能。最好的办法是定义一个' SteerableAndHitchable abstract class which inerits fromSteerable and includes aTrailerHitchmember of typeAttachable`,但那种东西即使只有两个能力也很恶心。以类型安全的方式添加更多功能不仅需要爆炸性数量的类;它将需要每个类别的属性数量不断增加。

于 2012-04-13T16:30:49.337 回答