【问题标题】:Subclass-specific override in JavaJava 中特定于子类的覆盖
【发布时间】:2011-05-31 12:19:50
【问题描述】:

我的问题如下:

我们有一个算法可以在内部使用

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

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

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

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

目前,我只能想到两种写干净代码的方法:

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

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

提前问候和感谢您,

Xaero。

【问题讨论】:

    标签: java inheritance frameworks polymorphism overloading


    【解决方案1】:

    听起来你应该使用泛型。喜欢

    interface Manipulator<E extends Expression> {
        public void manipulate(E expression);
    }
    
    class ProblemManipulator implements Manipulator<ProblemExpression> {
        public void manipulate(ProblemExpression expression) {
            // expression is a ProblemExpression
        }
    }
    

    【讨论】:

    • 当然。 Algorithm 处理 Manipulators 的方法也可以是通用的,例如public void process&lt;E extends Expression&gt;(Manipulator&lt;E&gt; manip, E expr).
    【解决方案2】:

    由于“问题”是一个不同的问题,它可以是一个扩展 Expression 的接口,如下所示:

    interface IProblemExpr extends Expression
    {   //additional methods
    }
    
    class ProblemExpression implements IProbExpr
    {
    }
    
    class ProblemManipulator()
    {
        ProblemManipulator(IProblemExpr expr)
        {
         ..
        }
    }
    

    【讨论】:

      【解决方案3】:

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

      例如,假设 ProblemManipulators 是 ProblemExpressions 的私有内部类 - 从 Expression#createManipulator(...) 获得。

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

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

      即,Expression 需要委托给适当的 Manipulator 的“manipulate()”方法。

      【讨论】:

      • 所以也许我可以使用我的第一个解决方案并假设该论点实际上是一个 ProblemExpression?这根本不需要泛型......
      【解决方案4】:

      我研究了泛型的工作方式,并提出了以下解决方案:

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

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

      接下来,我创建了一个通用的算法类。 需要两个类:

      1. 一些表情

      2. 操纵这种对象的东西

      我们得到:

      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 案例创建了一个实现: 我们需要一个表达式和一个操纵器

      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);
      

      对于字符串:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-07-28
        • 1970-01-01
        • 1970-01-01
        • 2012-10-12
        • 1970-01-01
        相关资源
        最近更新 更多