【问题标题】:abstract class and common code抽象类和通用代码
【发布时间】:2015-09-28 11:55:15
【问题描述】:

我有一个关于抽象类及其真正用途的问题。

考虑以下场景:

interface A {
    void execute();
}

class AOne implements A {
    public void execute() {
        x = getX();
        ..
        functionality specific to A
        ..
        y = getY();
        ..
        more funtionality specific to A
    }

    private X getX() {
        .. 
        return x;
    }

    private Y getY() {
        ..
        return y;
    }
}

class ATwo implements A {
    public void execute() {
        x = getX();
        ..
        functionality specific to B
        ..
        y = getY();
        ..
        more funtionality specific to B
    }

    private X getX() {
        ..
        return x;
    }

    private Y getY() {
        ..
        return y;
    }   
}

所以,我有一个接口 A,它声明了一个方法 execute() 和 2 个实现,AOne 和 ATwo 都实现/定义了 execute() 您会注意到两种实现中的执行方法都有一些共同的功能,即方法调用 getX() 和 getY()。两种实现中的这些方法做同样的事情,即它们在两个子类中重复。

现在,解决问题。我将通过在接口和实现之间实现一个抽象类来对上述代码进行一些修改。

interface A {
    void execute();
}

public abstract class AbstractA implements A {
    protected X getX() {
        .. 
        return x;
    }

    protected Y getY() {
        ..
        return y;
    }
}

class AOne extends AbstractA {
    public void execute() {
        x = getX();
        ..
        functionality specific to A
        ..
        y = getY();
        ..
        more funtionality specific to A
    }
}

class ATwo extends AbstractA {
    public void execute() {
        x = getX();
        ..
        functionality specific to B
        ..
        y = getY();
        ..
        more funtionality specific to B
    }
}

现在您会注意到,之前在实现类 AOne 和 ATwo 中重复的方法,即 getX() 和 getY() 已移至抽象类 AbstractA。另请注意,AbstractA 实现了 A,但没有提及 execute() 的任何实现。它只包含 AOne 和 ATwo 共有的代码

现在,我认为以上是对抽象类的错误使用和不正确的面向对象编程。抽象类不应该用来保存实现类通用的代码,至少不能以这种方式。

请有人对此有所了解,并让我知道上述是否正确。如果是,为什么,如果不是,为什么?

编辑:我相信我弄错了“通用代码”部分。我同意抽象类用于保存各种实现类共有的功能。但是,如果我们认为 getX() 和 getY() 方法是 AOne 和 ATwo 类都需要的某种实用程序,那么将它们拉到抽象类中是否仍然是一个好主意?

问题的底线是:是否应该使用抽象类来保存子类中的通用实用程序代码?

【问题讨论】:

  • 如果您不认为抽象类的用途是什么,那么您认为它们的用途是什么?
  • “抽象类不应该用来保存实现类通用的代码”。我认为这几乎是它们唯一有用的东西。

标签: java inheritance abstract-class


【解决方案1】:

你说过

不应使用抽象类来保存实现类的通用代码

这是不正确的。这正是他们的目的。

我会说您的 execute 方法可以更好地设计为 AbstractA 的一部分,因此:

public abstract class AbstractA implements A {
    protected abstract void doStuff(X x);
    protected abstract void doMoreStuff(X x, Y y);

    public void execute() {
        X x = getX();
        doStuff(x);
        Y y = getY();
        doMoreStuff(x, y);
    }

    // getX(), getY(), etc...
}

然后,您的实现类可以在这些抽象 doStuff() 和 doMoreStuff() 方法中隔离特定于实现的代码。

【讨论】:

  • doStuff,应该得到 x 作为参数,doMoreStuff x 和 y 作为参数
  • 是的,如果需要的话。
【解决方案2】:

我们会考虑具有不同类和方法名称的相同场景。

A - 动物

AbstractA - 人类

AOne - 男

ATwo - 女性

getX - 步行

getY - 坐下

如果我们考虑这种情况,让方法在抽象类 Human 中行走和坐坐并没有错。走路和坐着是人类阶级的常见行为。有些人可能有不同的步行方式。这种场景可以使用装饰器模式来处理。

如果方法 getX 和 getY 不是 AbstractA 的行为,最好创建适当的类并将方法移动到它/它们。

【讨论】:

    【解决方案3】:

    实例变量的上下文有两种可能性,我可以从您给定的代码中想到。

    1:如果您的getX 和`getY' 方法使用任何实例变量,那么您的代码是完美的,您可以通过这种方式使用抽象类/。

    2:如果您的getX 和 `getY' 方法不使用任何实例变量,则将这些方法替换为任何 util 类中的 static 方法并使用直接来自 util 类,例如 MyUtil.getXMyUtil.getY

    【讨论】:

      猜你喜欢
      • 2013-06-24
      • 1970-01-01
      • 2019-01-18
      • 1970-01-01
      • 1970-01-01
      • 2013-02-12
      • 1970-01-01
      • 2017-10-01
      • 1970-01-01
      相关资源
      最近更新 更多