繁体   English   中英

调用Java中的特定类方法(无多态性)

[英]Call a specific class method in Java (without 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. 重命名方法,以使它们不会彼此覆盖。 这是可行的,但并不安全(将来可能会忘记并导致问题),并且不受语言约束。

我知道这有点像代码气味,但是我认为没有更好的方法可以做到这一点。

基本上,我想做这样的事情:在Foo.updateMe我想专门调用Foo.updateX ,而不仅是调用多态的updateX

我相信,诸如C#中的new方法关键字之类的东西可以解决我的问题,但是Java似乎没有一种或任何其他方式来完成此任务。

编辑:

最后,我选择仅重命名有问题的方法。 我只有一个方法会导致此问题,并且这里提出了解决方案,尽管从设计的角度来看,声音会使该特定代码更难以理解和维护。

我会这样做:

  1. 从bar.updateMe()中删除updateX()调用,因为super.updateMe()已经调用过updateX()。
  2. 从Bar.updateX()调用super.updateX(),因为具有相同名称的方法应该扩展功能,而不是替换功能。

在这种情况下,不必更改Abc,并且两个updateX()方法都将被调用一次。

Java,所有实例方法调用都是通过动态绑定来调用的。 据我所知,没有优雅的方法可以完成您想要的。

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

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

Eli,看来您想取消OOP。 首先,这很糟糕。 如果您需要此更改您的设计。 Java是纯面向对象的语言,因此所有调用都是多态的。 如果扩展您的类并覆盖某些功能,则意味着您需要此功能,因此应调用此功能。 这就是从Bar调用updateX()的原因。

顺便说一句,要做您想做的事情,您应该创建静态方法并以这种方式调用它:Foo.updateX()。

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

缺点:由于updateX()从概念上讲是模板模式的一部分,因此它确实“感觉”起来像应该受到保护。

您不能将abstract private void updateX(); 在超类中强制用户实施它。

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

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

所有私有的updateMe()方法都会被调用。 (对我来说,这是所需要的,YMMV)

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM