有没有更好的方法来创建扩展另一个抽象类并添加新功能的抽象类?

时间:2017-11-07 15:54:47

标签: java oop inheritance design-patterns abstract-class

我有一个抽象类,它有一个具体的方法solve和几个solve使用的抽象方法:

public abstract class A{
    public void solve(){
       //code for solve

    }

    public abstract void a();
    public abstract void b();
}

然后我有另一个扩展B的课程A,使用solve中的抽象方法重新实现A方法,并添加新的方法c,d) 。它还有一个布尔字段,指示是否必须使用solve A或B中的{。}}。

public abstract class B extends A{
    boolean useA;
    public B(boolean useA){
        this.useA = useA
    }
    public void solve(){
        if(useA) super.solve();
        else // code for solve
    }

    public abstract void c();
    public abstract void d();
}

然后我有一个扩展C的具体类B,实现所有方法并有一个布尔值来指示是否必须使用solve。

public class C extends B{

    public C(boolean useA){
        super(useA);
    }

    ... //code for a,b,c and d
}

有没有办法做得更好?我想也许它不遵循OOP的原则。

2 个答案:

答案 0 :(得分:2)

有些人已经提到了装饰模式,也有策略模式。

然而,有人可能会使用lambdas注入一些处理程序。

处理程序可以使用公共服务/受保护的要求完成:

class A {
    public final f() {
       ...
       onF(x, y);
    }

    protected abstract void onF(X x, Y y);
}

解决方案复合体通常比没有继承更好,但作为字段,委托给字段。

因为@LonelyNeuron的答案提供了很好的论据。

简而言之:如果有疑问,请先将其编码,然后将其重构为优雅的模型。分离关注等等。

答案 1 :(得分:1)

问题是,OOP的最佳解决方案有时会过度设计。所以在某些情况下,花费最少的工作的解决方案将是最好的。

在这种情况下,很难判断。虽然您尝试创建一个Minimal,Complete和Verifiable示例很好,但它缺少有关应该继承内容的最重要信息:每个类的目的。例如,您可以想象将类B拆分为两个可能是有意义的,其中一个执行,另一个不重写solve(),但如果这是一个好主意,则只能决定问每个班级目的的正确问题。

我怀疑您是在问这些问题,因为您想知道在类中重用代码的最佳方法。如果是这种情况:不要。摘自this维基百科文章:

  

在大多数方面,仅仅为了代码重用而继承的类继承已经失宠了。主要关注的是实现继承不能保证多态可替代性 - 重用类的实例不一定能代替继承类的实例。另一种技术,显式委派,需要更多的编程工作,但避免了可替代性问题。在C ++中,私有继承可以用作实现继承的一种形式,而不具有可替代性。公共继承代表“is-a”关系,委托代表“has-a”关系,而私有(和受保护)继承可以被认为是“以”关系实现“。