在Java中调用特定的类方法(没有多态)

时间:2011-01-26 07:35:54

标签: java oop polymorphism

我遇到了Java问题。我有一个可以扩展的方法。问题是,这个方法调用了类的其他方法,并且这些方法也可以扩展。

考虑以下课程:

public class Foo {
    protected int xLast;

    public updateMe(int x, int y) {
        updateX(x);
    }

    protected updateX(int x) {
        this.xLast = x;
    }
}

此类由以下类扩展:

public class Bar extends Foo {
    protected int xAverage = 0;
    protected int xCount = 0;
    protected int y;

    public updateMe(int x, int y) {
        super.updateMe(x, y);       
        updateX(x);
        updateY(x);
    }

    protected updateX(int x) {
        this.xAverage = (this.xAverage * this.xCount) + x;
        this.xCount++;
        this.xAverage /= xCount;
    }

    protected updateY(int y) {
        this.y = y;
    }
}

还有这个班级:

public class Abc extends Foo {
}

当我执行以下操作时:

Foo myBar = new Bar();
myBar.updateMe(1, 2);

未调用Foo.updateX方法,但调用Bar.updateX方法两次。有几种解决方案,有些解决方案效果不佳或非常难看:

  1. Bar.updateX致电super.updateX。这将导致两个updateX方法被调用两次。
  2. 移除updateX中的Foo.updateMe来电,强制扩展类呼叫super.updateX。这将导致类Abc拥有它不需要的无用代码,否则Abc类将根本不会调用updateX
  3. 重命名方法,使它们不会相互覆盖。这样可行,但不安全(将来可能会被遗忘并导致问题)并且不会被语言强制执行。
  4. 我知道这有点像代码味道,但我认为没有更好的方法可以做到这一点。

    基本上我希望做到这样的事情:Foo.updateMe我想特别致电Foo.updateX,而不仅仅是多态updateX

    我相信像C#中的new方法关键字这样的东西可以解决我的问题,但是Java似乎没有一个或任何其他方法来实现这一点。

    修改

    最后我选择重命名违规方法。我有一个导致这个问题的方法,这里提出的解决方案,虽然从设计的角度来看声音会使这个特定的代码更难理解和维护。

4 个答案:

答案 0 :(得分:3)

我会这样做:

  1. 从Bar.updateMe()中删除updateX()调用,因为super.updateMe()已经调用了updateX()。
  2. 从Bar.updateX()调用super.updateX(),因为具有相同名称的方法应该扩展功能,而不是替换它。
  3. 在这种情况下,不必更改Abc,并且一次调用updateX()方法。

答案 1 :(得分:1)

Java,所有实例方法调用都是通过动态绑定调用的。据我所知,没有优雅的方法来实现你想要的东西。

如果你不关心原则和优雅,你可以在Foo检查一个实例的类。

public updateMe(int x, int y) { 
   if (getClass()==Foo.class)         
        updateX(x);     
}  

答案 2 :(得分:1)

以利,似乎你想要取消OOP。首先它很糟糕。如果您需要更改您的设计。 Java是纯面向对象的语言,因此所有调用都是多态的。如果你扩展了你的类并覆盖了一些它的功能就意味着你需要它,因此应该调用这个功能。这就是updateX()来自Bar的原因。

BTW做你想做的事你应该创建静态方法并以这种方式调用它:Foo.updateX()。

答案 3 :(得分:0)

您还可以将updateX()设为私有。然后,实现updateX()的子类是“隐藏”,而不是“覆盖”该方法。

缺点: 由于updateX()在概念上是模板模式的一部分,因此它真的“感觉”应该受到保护。

你不能放 abstract private void updateX(); 在超类中强制用户实现它。

updateMe()的所有实现必须始终记得调用updateX()

可能的缺点和可能的优势:

将调用所有私有updateMe()方法。 (对我而言,这是理想的,YMMV)

我最近遇到了这个问题并选择了这个解决方案,虽然我考虑重命名方法和非常接近(getClass()== MyFoo.class)技巧的东西。 IMO都是合理的。