Java:只能由超类调用的方法

时间:2015-04-02 12:02:27

标签: java inheritance encapsulation

我想阻止一个类调用自己的方法。该方法只能由其超类调用。

现在,我想不出任何方法来实现这一目标(干净利落)。但也许有人知道解决方案?

在代码中:

public abstract class A {
    protected abstract void foo();

    private void barA() {
        //do smth
        foo();
    }
}

public class B extends A {
    @Override
    protected void foo() {
        //do smth
    }

    private void barB() {
        //must not be able to call foo() here
    }
}

编辑:解释为什么我要这样做: A就是说一辆车。 B可以是汽车或飞机。方法foo()将是startEngines()。 - >我想确保引擎只能通过调用方法barA()来启动....这有什么意义吗?

6 个答案:

答案 0 :(得分:0)

我想这类似于AWT / Swing在组件上覆盖paint(Graphics g)方法(或Android活动中的onCreate(..))时遇到的问题。在这里,您将覆盖paint方法,但绝不应该调用它。

我认为你能做的最好的事情是在方法中添加文档,以澄清它应该从不由子类显式调用或重新评估你的设计。

答案 1 :(得分:0)

this answer有一个很好的暗示。

在你的班级(B级)中添加以下方法:

public static String getMethodName(final int depth)
{
  final StackTraceElement[] ste = Thread.currentThread().getStackTrace();
  return ste[ste.length - 1 - depth].getMethodName();
}

并将foo方法in class B更改为:

   @Override
    protected void foo() {
        //....
        if (getMethodName(0)=="barB"){
           // tell you are not able to call barB
        }
    }

答案 2 :(得分:0)

你可以把接口作为成员放在通过构造函数给它的超类中。子类实现了该方法,但除非将其设置为静态,否则无法调用它。

interface Foo {
    void stopEngines();
    void startEngines();
}

abstract class Base {
    final private Foo foo;

    public Base(final Foo foo) {
        this.foo = foo;
    }
    private void barA() {
        // do smth
        foo.startEngines();
    }
}

class Child extends Base {
    public Child() {
        super(new Foo() {
            boolean engineRunning;
            @Override
            public void stopEngines() {
                this.engineRunning = false;
            }

            @Override
            public void startEngines() {
                this.engineRunning = true;
            }
        });
    }
    private void barB() {
        // can't call startEngines() or stopEngines() here
    }
}

class Child2 extends Base {
    public Child2() {
        super(new Foo() {
            @Override
            public void stopEngines() {
                stopEngines();
            }

            @Override
            public void startEngines() {
                startEngines();
            }
        });
    }
    static void stopEngines() {
        // influence some static state?
    }
    static void startEngines() {
        // influence some static state?
    }
    private void barB() {
        // can call stopEngines() and startEngines(), but at least they have to be static
    }
}

当然,这不是你要求的,但我猜你可以用Java做的事情。

看到startEngines的解释,这个解决方案甚至可能就足够了。 我猜你不会关心这个类调用它的静态方法,因为它们只能影响很少使用的静态。匿名接口实现中的方法可以相互调用,但我想这没关系,因为您似乎只是试图阻止其他人以某种不同的方式启动引擎。

答案 3 :(得分:0)

有一种方法可以做到,但您需要使用Google Error Prone。这是Java编译器的扩展,旨在提供越来越多有用的警告和错误(类似于FindBugs和PMD,但错误警报较少)。我只能推荐它,它已经帮助我们找到了一些错误。

具体来说,它包含注释@ForOverride和根据compile-time check。此注释旨在用于子类和任何其他类不应调用的受保护方法,但仅用于定义类。

所以使用

public abstract class A {
    @ForOverride
    protected abstract void foo();

    private void barA() {
        //do smth
        foo();
    }
}

完全达到你想要的效果。

您可以将Error Prone集成到Maven和Ant等大多数构建系统中。当然,如果有人在没有Error Prone的情况下编译源代码(例如在Eclipse中),它将不会有帮助,但在连续集成系统中使用它仍然可以让你找到这样的问题。源代码仍然与常规Java编译器保持兼容(假设您在类路径上有error_prone_annotations.jar),其他编译器将不会执行额外的检查。

答案 4 :(得分:0)

考虑到您的车辆和发动机情况,我认为您需要重新考虑一下您的设计。 您的车辆可能是汽车,飞机等,但是汽车,飞机......每个都有不同的引擎,因此采用不同的startEngine方法。因此,如同您所做的那样将您的类车辆声明为抽象,并将类startEngine声明为抽象方法。接下来,子类Vehicle并在其中实现startEngine,现在您可以在子类实例上调用startEngine

abstract class Vehicle{
    abstract void startEngine();
}

public class Car extends Vehicle{
   public void startEngine(){  
      //implementation  
   }  
   public static void main(String[] arg){
       Vehicle v=new Car();
       v.startEngine();
   }
}

答案 5 :(得分:0)

通过Interface将匿名内部类添加到barA方法,因此您需要为foo()(功能接口)实现一个方法。它不属于B类。