抽象类和公共代码

时间:2015-09-28 11:55:15

标签: java inheritance abstract-class

我对抽象类及其真实目的有疑问。

考虑以下情况:

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都实现了/ define execute() 您会注意到两个实现中的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常用的代码

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

有人可以对此有所了解,并告诉我上述内容是否正确。如果是,为什么,如果不是为什么?

编辑:我相信我得到了#34;公共代码"部分错了。我同意抽象类用于保存各种实现类的通用功能。但是如果我们认为方法getX()和getY()是AOne和ATwo类需要的某种实用程序,那么将它们提升到抽象类仍然是一个好主意吗?

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

3 个答案:

答案 0 :(得分:8)

您已声明

  

抽象类不应该用于保存实现类的通用代码

这是不正确的。这正是他们所要做的。

我会说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()方法中分离特定于实现的代码。

答案 1 :(得分:1)

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

A - 动物

AbstractA - Human

AOne - 男性

ATwo - 女性

getX - walk

getY - 坐

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

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

答案 2 :(得分:-1)

实例变量的上下文中有两种可能性我可以根据您给定的代码进行思考。

1:如果你的getX和`getY'方法使用任何实例变量,然后你的代码是完美的,你可以用这种方式使用抽象类/.

2:如果你的getX和`getY'方法不使用任何实例变量,然后在任何util类中使用 static 方法替换这些方法,并直接从util类使用,如 MyUtil.getX MyUtil .getY