Java中特定于子类的重写

时间:2011-05-31 12:19:51

标签: java inheritance frameworks polymorphism overloading

我的问题如下:

我们有一个内部使用

的算法
  • 具有“String getContent()”方法的表达式对象
  • 使用“表达式操作(表达式e)”方法操作表达式的操纵器对象

这将成为Java中的框架。 要解决实际问题,需要提供具体的实现 Expression和Manipulator以及Algorithm类将完成剩下的工作。

假设我们需要一个ProblemExpression和一个ProblemManipulator 针对特定问题。

ProblemExpression可能包含很多新字段, 可以由ProblemManipulator使用。

现在,我只能想到两种编写干净代码的方法:

  • 让ProblemManipulator.manipulate假设它的参数是ProblemExpressions
  • 使用instanceOf

但我觉得这不是我应该这样做的方式。 还有其他建议吗?

提前问候并感谢,

Xaero。

4 个答案:

答案 0 :(得分:5)

听起来你应该使用Generic。像

interface Manipulator<E extends Expression> {
    public void manipulate(E expression);
}

class ProblemManipulator implements Manipulator<ProblemExpression> {
    public void manipulate(ProblemExpression expression) {
        // expression is a ProblemExpression
    }
}

答案 1 :(得分:1)

由于“问题”是一个不同的问题,它可以是一个扩展表达式的接口:

interface IProblemExpr extends Expression
{   //additional methods
}

class ProblemExpression implements IProbExpr
{
}

class ProblemManipulator()
{
    ProblemManipulator(IProblemExpr expr)
    {
     ..
    }
}

答案 2 :(得分:0)

如果可以公开访问ProblemExpresions和ProblemManipulator,那么泛型是不够的。 起初我认为某种工厂框架会起作用。 即,表达式需要能够创建操纵器,反之亦然。

例如,问题操纵者是ProblemExpressions的私有内部类 - 从Expression#createManipulator(...)获得。

然而,这并没有完全解决这个问题......最后,如果允许算法“保持对Expression和Manipulator的引用”,并且可以获得不同的无关实现,那么算法实现总是可以(如果写得不正确)最终为给定的表达式调用错误的操纵器 - 在编译时无法完成任何操作以防止此运行时错误,因为可以使用任何表达式调用所有操纵器。

因此,在我看来,操纵器(或表达式)的调用必须“通过”表达式(或相反的操纵器),从而确保为给定的表达式调用正确的操纵器。

即表达式需要'manipulate()'方法,该方法委托给相应的操纵器。

答案 3 :(得分:0)

我研究了仿制药的工作方式,并提出了以下解决方案:

首先,我创建了两个类,一个用于表达式,另一个用于操纵器:

public class ObjectExpression { }

public class ObjectManipulator <E extends ObjectExpression> {

    public void calculate(Set<E> objects) {
        ... // Do something
    }
}

接下来,我创建了一个Algorithm类,它是通用的。 需要两个课程:

  1. 一些表达

  2. 操纵此类型对象的东西

  3. 我们得到:

    public class Algorithm <F extends ObjectExpression, E extends ObjectManipulator<F>> {
        E om;
    
        public Algorithm( E om ) {
            this.om = om;
        }
    
        public void run(Set<F> objects) {
            om.calculate(objects);  
        }   
    }
    

    然后,我为String case创建了一个实现: 我们需要一个表达式和一个操纵器

    public class StringExpression extends ObjectExpression {
    }
    
    public class StringManipulator extends ObjectManipulator<StringExpression> {
    
        @Override
        public void calculate(Set<StringExpression> objects) {
            // Do String stuff
        }
    }
    

    然后,我们可以按如下方式运行算法:

    Algorithm<ObjectExpression, ObjectManipulator<ObjectExpression>> algo1 = new Algorithm<ObjectExpression, ObjectManipulator<ObjectExpression>>(manipo);
    Set<ObjectExpression> objects = new HashSet<ObjectExpression>();
    ... // fill set
    algo1.run(objects);
    

    对于Strings:

    StringManipulator manips = new StringManipulator();
    Algorithm<StringExpression, StringManipulator> algo2 = new Algorithm<StringExpression, StringManipulator>(manips);
    Set<StringExpression> strings = new HashSet<StringExpression>();
    ... // fill set
    algo2.run(strings);
    

    对我来说,这似乎是一个优雅的解决方案。 你怎么看? 任何替代/改进?