Java 中特定于子类的重写

发布于 2024-11-10 12:15:27 字数 523 浏览 2 评论 0原文

我的问题如下:

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

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

这将成为一个框架在爪哇。 解决实际问题需要给出具体的实现 表达式和操纵器以及算法类将完成剩下的工作。

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

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

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

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

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

预先问候并感谢您,

Xaero。

My problem is as follows:

We have an Algorithm that works internally with

  • Expression-objects that have a "String getContent()" method
  • Manipulator-objects that manipulate on Expressions using the "Expression manipulate(Expression e)" method

This will become a framework in Java.
To solve a real problem, one needs to give a specific implementation
of both an Expression and a Manipulator and the Algorithm class will do the rest.

Let's say we need a ProblemExpression and a ProblemManipulator
for a specific problem.

The ProblemExpression may contain a lot of new fields,
which can be used by the ProblemManipulator.

Right now, I can only think of two ways to write clean code:

  • Let ProblemManipulator.manipulate assume its arguments are ProblemExpressions
  • Use instanceOf

But I've got the feeling this is not how I should do it.
Any other suggestions?

Regards and thank you in advance,

Xaero.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

去了角落 2024-11-17 12:15:27

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

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

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

Sounds like you should use a Generic. Like

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

class ProblemManipulator implements Manipulator<ProblemExpression> {
    public void manipulate(ProblemExpression expression) {
        // expression is a ProblemExpression
    }
}
擦肩而过的背影 2024-11-17 12:15:27

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

interface IProblemExpr extends Expression
{   //additional methods
}

class ProblemExpression implements IProbExpr
{
}

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

As "Problem" is a different problem, it can be an interface that extends Expression like so:

interface IProblemExpr extends Expression
{   //additional methods
}

class ProblemExpression implements IProbExpr
{
}

class ProblemManipulator()
{
    ProblemManipulator(IProblemExpr expr)
    {
     ..
    }
}
故事灯 2024-11-17 12:15:27

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

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

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

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

即,表达式需要“manipulate()”方法,该方法委托给适当的操纵器。

Generics are not enough, if both ProblemExpresions and ProblemManipulators can be accessed publicly.
At first i thought some kind of factory framework would do the trick.
I.e., either Expressions need to be able to create Manipulators or vice-versa.

for example, say ProblemManipulators were private inner classes of ProblemExpressions - obtained from Expression#createManipulator(...).

However, this does not quite do the trick ... in the end, if the Algorithm is allowed to 'hold onto references to' both the Expression and Manipulator, and can obtain different unrelated implementations, then the Algorithm implementation can always (if incorrectly written) wind up invoking the wrong Manipulator for a given Expression - nothing can be done at compile time to prevent this runtime mistake as all Manipulators can be invoked with any Expression.

So, it seems to me that invocation of the Manipulator (or Expression) must 'go thru' the Expression (or conversely the Manipulator) thus ensuring that the correct Manipulator is invoked for the given Expression.

I.e., Expression needs 'manipulate()' method which delegates to the appropriate Manipulator.

稚气少女 2024-11-17 12:15:27

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

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

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

对我来说,这似乎是一个优雅的解决方案。
你怎么认为?
有什么替代方案/改进吗?

I studied the way generics work, and I came up with the following solution:

First, I created a two classes, one for the expression and one for the manipulator:

public class ObjectExpression { }

public class ObjectManipulator <E extends ObjectExpression> {

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

Next, I created an Algorithm class, which is generic.
Two classes are needed:

  1. Some expression

  2. Something that manipulates this type of object

We get:

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

Then, I created an implementation for the String case:
we need an expression and a manipulator

public class StringExpression extends ObjectExpression {
}

public class StringManipulator extends ObjectManipulator<StringExpression> {

    @Override
    public void calculate(Set<StringExpression> objects) {
        // Do String stuff
    }
}

Then, we can run the Algorithm as follows for Objects:

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

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

To me, this seems an elegant solution.
What do you think?
Any alternatives/improvements?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文