为什么抽象类被认为是“不完整的”?

huangapple go评论75阅读模式
英文:

Why an abstract class is "considered incomplete"?

问题

我们知道抽象类是一个不完整的类(它的所有方法都没有被实现 - 抽象方法),但抽象类也被认为是“被视为不完整的类”。那么,“被视为不完整”的正确含义(定义)是什么?是指一个类可以同时拥有已实现和未实现的方法吗?还是指另一种情境?

请告诉我,非常感谢!

英文:

We known that an abstract class is an incomplete class (all its methods are unimplemented - # abstract method), but abstract class is also known that "a class is CONSIDERED INCOMPLETE". So, what is the correct meaning (definition) of CONSIDERED INCOMPLETE, is that a class can have both implemented and unimplemented method? or another context?

Please let me know, thank you very much!

答案1

得分: 1

这个规范说:“抽象类是一个不完整的类,或者被视为不完整的类”,因为你可以有一个完全实现的抽象类(例如参见java.awt.event.MouseAdapter)。从技术上讲,它是完整的,但它不应该以这种方式使用。

现在,人们可能会通过在接口中使用默认方法来实现这些抽象适配器类(如果在特定情况下接口对于这个目的是合适的话……)。


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

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

那么,让我们仔细看看实现了接口java.awt.event.KeyListener的类java.awt.event.KeyAdapter。根据java.awt.event.KeyEvent的描述,KeyListener 的实现将为您键入的每个字符接收三个事件(有关详细信息,请参阅KeyEvent的描述):

  1. KEY_PRESSED – 由 keyPressed() 处理
  2. KEY_TYPED – 由 keyTyped() 处理,但仅在能够生成有效的 Unicode 字符时才会触发
  3. KEY_RELEASED – 由 keyReleased() 处理

如果您的程序只想要响应文本输入,那么它只对 KEY_TYPED 事件感兴趣,KeyListener.keyPressed()KeyListener.keyReleased() 的实现可以保持为空(尽管它们仍然必须实现)。

如果您的程序是某种游戏的实现,您可能更关注按下的键;在这种情况下,KeyListener.typed() 可以保持为空。

接下来,这些监听器接口经常被用作匿名类,如下所示:

…
KeyListener listener = new KeyAdapter()
{
    @Override
    void keyTyped(KeyEvent event)
    {
        // 对事件做些什么…
    }
};
…

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

…
KeyListener listener = new KeyListener()
{
    @Override
    void keyReleased(KeyEvent event) { /* 什么也不做 */ }

    @Override
    void keyPressed(KeyEvent event) { /* 什么也不做 */ }

    @Override
    void keyTyped(KeyEvent event)
    {
        // 对事件做些什么…
    }
};
…

额外的代码行并没有真正提高可读性。

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


这些适配器类只是一个不包含任何抽象方法的抽象类的一个可能的用例。但我承认,大多数情况下,它们与接口中的默认方法更配合得更好——因为这些默认方法当然已经加入了Java!适配器类从Java 1.1开始存在,我想……就像语言规范中的那些短语一样!

英文:

The specification says "An abstract class is a class that is incomplete, or to be considered incomplete" because you can have an abstract class that is fully implemented (see java.awt.event.MouseAdapter as an example). Technically, it is complete, but it is not meant to be used this way.

Nowadays, one might implement those abstract adapter classes by interfaces with default methods (if for that particular case an interface would be appropriate for that purpose at all …).


The idea behind the adapter classes was to provide a base implementation of particular interface that allows only those methods that are of interest for the current use case.

The interfaces java.awt.event.MouseMotionListener and java.awt.event.MouseWheelListener that are implemented by java.awt.event.MouseAdapter are not very well suited to illustrate the benefit of this approach, because they do have only two or one method. In addition, that MouseAdapter class implements also java.awt.event.MouseListener but does not implement any method from that interface …

So lets have a closer look to the class java.awt.event.KeyAdapter that implements the interface java.awt.event.KeyListener. According to the description for java.awt.event.KeyEvent, an implementation of KeyListener will receive three events for each character you type (for the exact details, refer to the description of KeyEvent):

  1. KEY_PRESSED – handled by keyPressed()
  2. KEY_TYPED – handled by keyTyped(), but only if a valid Unicode character could be generated
  3. KEY_RELEASED – handled by keyReleased()

If your program wants to respond to text input only, it is only interested on the KEY_TYPED events and the implementations of KeyListener.keyPressed() and KeyListener.keyReleased() could remain empty (although they have to be implemented nevertheless!).

In case you program is an implementation of a game of some kind, you might be more interested in the pressed keys; in that case, KeyListener.typed() may remain empty.

Next, these listener interfaces are often used as anonymous classes, like this:

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

Without using the adapter class, the same code would look like this:

…
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 …
    }
}
…

The additional lines do not contribute to readability, not really.

As said, if the methods in the interface would provide an empty default implementation, the second version (new Interface(){…}) would look like the first one.


These adapter classes are only one possible use case for an abstract class that does not contain any abstract method. But I confess that most of them would work better with default methods in interfaces – since these default methods made their way into Java, of course! The adapter classes are there since Java 1.1, I think … like those phrase from the language specification!

答案2

得分: 0

正如你所提到的,抽象类可以仅具有方法签名/契约,说明方法的名称是什么,它接受什么参数(如果有的话),以及它有什么返回类型(或void),如果它不返回任何内容的话 - 但实际上不实现它。想象一下,你创建了一个这个类的对象(顺便说一下,你是不能这样做的),但如果你为了讨论的目的而这样做了,然后调用其中一个没有提供实现的抽象方法,你认为会发生什么?基本上,你正在尝试调用没有任何实现的内容,这将是无效的。因此,由于在抽象类中有一个或多个方法可能没有实现,所以我们认为抽象类更像是一个契约,而不是一个完全实现/完整的类。

英文:

As you mentioned, an abstract class CAN have just method signature/contract stating what the method name is, what arguments it take (if any) and what return type it has (or void) if it doesn't return anything - BUT without actually implementing it. And lets imagine, you create an object of this class (which by the way you can not) but if you would just for the sake of discussion, and then CALL one of those abstract methods where implementation was not provided, what do you think should happen? Basically, you are trying to call something that does not have implementation at all and that will be invalid. And hence, since there is a possibility of one or more methods not implmented in your the abstract class, we considereded an abstract class as more of a contract than considering it as fully implemented/complete class.

答案3

得分: 0

抽象类用于将简单逻辑与真实实例分离。

逻辑相对于真实事件或实例始终是不完整的。例如,猫和老虎都可以咆哮,但它们的声音是不同的。因此,我们可以抽象出roar()方法,这是一种逻辑。然后,通过使用不同的声音实例来实现方法,如miao~~miao~~aowu~~aowu~~

可以看出,逻辑是简单而精练的,但它是不完整的,而实例则是完整的但冗余的。

问题:一个类可以同时拥有已实现和未实现的方法吗?还是另一种情况?

回答
您无需实现抽象类的所有方法,但必须实现其所有抽象方法。

实际上,扩展抽象类与扩展普通类没有区别。这与实现接口不同。由于您正在扩展,因此您正在创建一个子类,因此可以根据需要添加许多方法和属性。

英文:

An abstract class is used to abstract simple logic from a real instance.

Logic is always relative incompelete to real event or instance. For example, Cat and Tiger can all roar, but their voices are different. So, we can abstract the roar() method, which is logic. And then implement the method by using different voice like miao~~miao~~ and aowu~~aowu~~ which are real instance.

You can see it, logic is simple and refined, but it is incomplete, while real instance is completed but redundant.

Question: Is that a class can have both implemented and unimplemented method? or another context?

Answer:
You don't have to implement all methods of an abstract class but you must implement all abstract methods of it.

In fact, extending an abstract class has no difference then extending a normal class. It's not like implementing interfaces. Since you're extending you are creating a subclass, thus you can add as many methods and attributes as you need.

huangapple
  • 本文由 发表于 2020年7月23日 17:06:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/63050701.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定