是否有任何理由要在类中定义每个方法的抽象类?

use*_*521 33 java inheritance

似乎抽象类意味着类的定义不完整,因此无法实例化.

我看到了一些简单的Java代码,它有一个抽象类,定义了所有方法.然后我想知道,为什么他们把它作为抽象类而不是真正的类呢?他们这样做是为了让我们无法从这个抽象类中实例化吗?或者他们从制作一个定义了所有内容的抽象类中获得了其他好处?

Phi*_*ipp 43

即使所有方法都有默认实现,这些实现也可能在应用程序的上下文中实际上没有意义.这些方法可能只进​​行内部簿记,而实际有用的实现必须由派生类提供,派生类执行它需要做的事情,然后调用超类方法.

然而,这只是猜测.你必须展示一个实际的例子来说明这个设计的原因.

举个例子,我们来看一个简单的游戏引擎吧.我的GameObject游戏中有很多不同的东西.

  • 有些是可见的,所以我的基础类得到一个draw()方法.但是可能存在不可见的对象,例如根本没有出现的触发区域,因此我将其实现为基类中的无操作.

  • 有些人在遇到某些事情时会做一些事情,所以每个人都会得到一个collide(other)方法.但是当它们像纯粹的视觉粒子效果碰撞时,有些人什么都不做,所以我也在基类中提供了一个no-op.

  • 有些人会在每场比赛中做点什么,所以他们得到一个update()方法.但有些物体,如墙壁,可能根本不会做任何事情.所以我也提供了一个no-op.

那么当我有一个看不见的对象,它本身没有做任何事情并且不与任何东西互动时,我该怎么办?在游戏中没有理由这样做.所以我做了这个基础课abstract.从理论上讲,你可以实例化它,因为所有方法都有一个实现,但实际上你没有理由这样做,当你尝试时,你误解了我的游戏引擎是如何工作的.

  • 此外,为基类中的每个虚方法提供普通或无操作实现意味着派生类只需要实现这些方法的子集以实现可实例化.这完全是一个词. (6认同)
  • 此外,它可能即使有意义,但实现是*简单*并且需要按顺序扩展,例如,可扩展或宁静.这也可以解释为什么一个完整的类被标记为*abstract* - 以诱使子类更仔细地查看实现细节. (2认同)
  • 这些类的Java API示例:`KeyAdapter`,`MouseAdapter`,`MouseMotionAdapter`.其他例子:`junit.framework.TestCase`. (2认同)

Raf*_*ter 22

一个典型的用例是创建适配器类.考虑一个回调接口,您可以在其中收到10个不同事件的通知,但通常只对其中一些事件感兴趣.使用适配器类,您可以提供空实现,这样实际的回调只需要在扩展适配器后实现那些感兴趣的方法.通过使适配器变得抽象,您表达了这样一个事实:实例化适配器本身是没有意义的,因为它没有任何用处.

从Java 8开始,您将不再实现此类适配器,而是使用接口的默认方法.

  • Java API中的一个示例是[KeyAdapter](https://docs.oracle.com/javase/7/docs/api/java/awt/event/KeyAdapter.html)类,它是一个实现的抽象类KeyListener接口中的每个方法.这允许您扩展KeyAdapter并仅覆盖您要实现的方法,而不是实现KeyListener并实现一堆空方法. (6认同)

zmb*_*mbq 11

就在这里.有时你知道你正在创建一个抽象类 - 一个必须从中派生出来才能产生任何实际意义的类,但是你想为所有方法提供一个默认实现.这不会发生很多,但确实会发生.

更新:我刚才有这样的案例.我正在录制各种用户生成的事件.每个事件都有一个TimeSpan和一个描述,它们都有其他的东西.我创建了一个基本事件类:

public abstract class BaseEvent
{
    public TimeSpan EventTime {get; private set;}
    public string Description {get; protected set;}

    public BaseEvent(TimeSpan time, string desc) ...
}
Run Code Online (Sandbox Code Playgroud)

当然,这是C#而不是Java,但如果我用Java编写,我本可以做同样的事情)

  • 这种模式有时被称为"适配器". (2认同)

kin*_*iko 7

您可以拥有一个实现多个接口的抽象类.您不需要在抽象类中实现这些方法,但是您需要在抽象类的子类中实现它们.

例如

public interface MyInterface{
    void hello();
}

public abstract class Clazzy implements MyInterface {
//I need not have the interface method.
}

public class MySubclass extends Clazzy {

    @Override
    public void hello() {
        // I need to be here
    }

}
Run Code Online (Sandbox Code Playgroud)