Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/310.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在这种情况下,为什么在抽象类上使用接口?_Java_Inheritance_Interface - Fatal编程技术网

Java 在这种情况下,为什么在抽象类上使用接口?

Java 在这种情况下,为什么在抽象类上使用接口?,java,inheritance,interface,Java,Inheritance,Interface,我在这里读了一篇博文: 它说: 事实上,有些演员也是导演。如果我们使用的是接口而不是抽象类,那么我们可以使用抽象类实现同样的功能。不幸的是,替代方案将需要多达2^n(其中n是属性的数量)的可能组合,以支持所有可能性 问题:为什么抽象类在这里更好?为什么是2^n public abstract class ActorDirector implements Actor,Director{ } 您不能从多个类(抽象类或非抽象类)继承,但可以实现多个接口 如果要创建抽象类,则每个组合都需要一个抽象类(

我在这里读了一篇博文:

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

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

public abstract class ActorDirector implements Actor,Director{
}

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

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


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

在决定是否需要
抽象类时,您需要回答的问题很简单

实现这些接口的任何类之间是否有任何共享方法的公共实现?如果这是yes,那么您将把该实现放在
抽象类中

如果这是,那么您只需将两者组合成一个
接口
,并让所有实现类提供其自定义的非共享实现

两者都要做,这绝对是有道理的。拥有一个超级接口,该接口允许绕过单一继承限制,同时还具有该超级接口的
抽象
实现,以便为接口中任何方法的任何共享默认实现提供高内聚性


这些决策越容易,你获得的解决这些问题的经验就越多

我想你误解了这篇文章:作者并不是说抽象类在这种情况下更好——相反,他认为接口更合适


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

继承有两个部分:

  • 派生类可以将其父类的公共或受保护的方法或字段视为自己的方法或字段。
  • 在请求基类型对象的大多数上下文中,可以用派生类型对象替换基类型对象。 实现接口的类只获得后者的好处,而从抽象类继承的类则实现了两者。另一方面,这一好处带来了一个限制:因为一个类只能将另一个类的方法和字段视为自己的,所以一个类只能从一个抽象类继承。相反,一个类可以实现(因此可以替代)任意数量的接口


    不要担心抽象类的组合爆炸。假设一些车辆可以转向(例如小型汽车),其他车辆可以附加动力(例如铁路机车),而一些车辆可以两者兼有(例如皮卡车)。
    皮卡车
    应该能够满足需要能够
    转向
    的车辆的代码,以及需要能够
    附加动力
    的车辆的代码。但是,如果
    Steer
    AttachFollower
    都是抽象类,则无法声明
    PickupTruck
    ,因此一个实例可以执行这两个功能。最好的办法是定义一个“SteerableAndHitchable
    抽象类,该类从
    Steerable
    中继承,并包含一个类型为
    Attachable的
  • TrailerHitch
    成员”,但即使只有两个能力,这种事情也很棘手。以类型安全的方式增加更多的能力不仅需要爆炸式的职业数量;它需要每个类的属性数量不断增加。

    等等,你是在问为什么接口更好,还是抽象类更好?+1这就是为什么你可能需要
    2^n
    抽象类的组合,而不是
    n
    接口。@PeterLawrey:一个人可以用2^n个抽象类的组合做什么,而这些抽象类是他不能没有的?继承抽象类
    X
    并复制抽象类
    Y
    的所有特性但不从中继承的抽象类将不能替代
    Y
    。人们可以为基础抽象类的不同组合定义2^n个这样的类,但我认为这不是必需的,也不是有用的。我认为无论有多少抽象类,都无法实现所需的语义。如果存在能力A、B和C,并且一个使用者需要具有能力AB、一个使用者需要BC和一个使用者需要AC的对象,则无法定义一个能够满足所有三个使用者的类,除非要求上述使用者之一必须要求该类,而不是一个更狭隘地满足其需求的类。@supercat我认为这是本文试图表达的观点:为了让用户做出所有行为的所有组合,作者不仅需要为a、B和C提供抽象类,而且还需要提供抽象类
    public abstract class ActorDirector implements Actor,Director{
    }