为什么摘要 class 是 "considered incomplete"?

Why an abstract class is "considered incomplete"?

我们知道抽象 class 是一个不完整的 class(它的所有方法都未实现 - # 抽象方法),但是抽象 class 也被称为“一个 class 是 被认为是不完整的 ”。那么,CONSIDERED INCOMPLETE 的正确含义(定义)是什么 class 可以同时具有已实现和未实现的方法?还是其他上下文?

请告知,非常感谢!

正如您所提到的,抽象 class 可以只有方法 signature/contract 说明方法名称是什么,它采用什么参数(如果有的话)以及它具有什么 return 类型(或无效)如果它没有 return 任何东西 - 但没有实际实施它。让我们想象一下,您创建了一个 class 的对象(顺便说一下,您不能)但是如果您只是为了讨论,然后调用其中一个未提供实现的抽象方法,那会怎样你认为应该发生吗?基本上,您正在尝试调用根本没有实现的东西,这将是无效的。因此,由于有可能在您的摘要 class 中未实现一种或多种方法,我们认为摘要 class 更像是一种合同,而不是完全 implemented/complete class.

抽象class用于从真实实例.

中抽象出简单的逻辑

逻辑总是相对于真实的事件或实例而言是相对不完整的。比如猫和虎都会吼,只是声音不同而已。所以,我们可以抽象出roar()这个方法,这就是逻辑。然后通过使用不同的语音来实现该方法,例如 miao~~miao~~aowu~~aowu~~ 这是真实的实例。

可以看到,逻辑简单精炼,但不完整,实例完整但冗余。

问题: class 是否可以同时拥有已实现和未实现的方法?还是其他上下文?

回答:
您不必实现抽象的所有方法 class 但您必须实现它的所有抽象方法。

事实上,扩展抽象 class 与扩展普通 class 没有区别。这不像实现接口。由于您正在扩展,因此您正在创建子class,因此您可以根据需要添加任意数量的方法和属性。

规范说“摘要 class 是不完整的 class,或者 被视为 不完整”,因为您可以有一个摘要 class 已完全实现(参见 java.awt.event.MouseAdapter 作为示例)。 技术上,它是完整的,但并不意味着要这样使用。

如今,人们可能会通过具有默认方法的接口来实现这些抽象适配器 classes(如果对于特定情况,接口完全适合该目的……)。


适配器 classes 背后的想法是提供特定接口的基本实现,该接口仅允许那些对当前用例感兴趣的方法。

java.awt.event.MouseAdapter实现的接口java.awt.event.MouseMotionListenerjava.awt.event.MouseWheelListener不太适合说明这种方法的好处,因为它们确实只有两个或一个方法。此外,MouseAdapter class 也实现了 java.awt.event.MouseListener 但没有实现该接口的任何方法...

所以让我们仔细看看 class java.awt.event.KeyAdapter that implements the interface java.awt.event.KeyListener. According to the description for java.awt.event.KeyEventKeyListener 的实现将为您键入的每个字符接收三个事件(有关确切的详细信息,请参阅KeyEvent 的描述):

  1. KEY_PRESSED – 由 keyPressed()
  2. 处理
  3. KEY_TYPED – 由 keyTyped() 处理,但前提是可以生成有效的 Unicode 字符
  4. KEY_RELEASED – 由 keyReleased()
  5. 处理

如果您的程序只想响应文本输入,它只对 KEY_TYPED 事件感兴趣,并且 KeyListener.keyPressed()KeyListener.keyReleased() 的实现可以保持为空(尽管它们有尽管如此,还是要实施!)。

如果您的程序是某种游戏的实现,您可能对按下的键更感兴趣;在这种情况下,KeyListener.typed() 可能仍为空。

接下来,这些监听器接口经常被用作匿名classes,像这样:

…
KeyListener listener = new KeyAdapter()
{
    @Overwrite
    void keyTyped( KeyEvent event )
    {
        // Do something with the event …
    }
}
…

如果不使用适配器 class,相同的代码将如下所示:

…
KeyListener listener = new KeyListener()
{
    @Overwrite
    void keyReleased( KeyEvent event ) { /* Does nothing */ }

    @Overwrite
    void keyPressed( KeyEvent event ) { /* Does nothing */ }

    @Overwrite
    void keyTyped( KeyEvent event )
    {
        // Do something with the event …
    }
}
…

额外的行对可读性没有帮助,不是真的。

如前所述,如果接口中的方法将提供一个空的默认实现,则第二个版本 (new Interface(){…} ) 看起来像第一个。


这些适配器 class 只是不包含任何抽象方法的抽象 class 的一种可能用例。但我承认,它们中的大多数在接口中使用默认方法会更好——因为这些默认方法当然进入了 Java!适配器 classes 自 Java 1.1 以来就存在,我认为......就像语言规范中的那些短语!