繁体   English   中英

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

[英]Java: method only callable by superclass

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

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

在代码中:

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()来启动引擎。这有意义吗?

我猜这与AWT / Swing在组件上重写paint(Graphics g)方法(或Android Activities中的onCreate(..)遇到的问题类似。 在这里,您将重写paint方法,但是永远不要调用它。

我认为您可以做的最好的事情是向该方法中添加文档,以阐明该子类永远不要显式调用它,或者重新评估您的设计。

这个答案有一个很好的提示。

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

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

并将in class Bfoo方法更改为:

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

您可以将接口作为成员通过构造函数提供给它的超类。 子类实现该方法,但只能通过使其静态化而不能调用它。

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的说明,该解决方案甚至可以满足要求。 我猜您不会在意该类调用其静态方法,因为它们只能影响很少使用的静态状态。 匿名接口实现中的方法可以相互调用,但是我想这样就可以了,因为您似乎只是想防止其他人以某种不同的方式启动引擎。

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

具体来说,它包含一个注释@ForOverride和一个相应的编译时检查 此批注旨在用于子类和任何其他类不应该调用的受保护方法,而只能用于定义类。

所以用

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 ),其他编译器将完全不执行其他检查。

考虑到您的车辆和发动机情况,我认为您需要重新考虑一下设计。 您的车辆可能是汽车,飞机等,但是汽车,飞机……每个都有独立的引擎,因此有不同的startEngine方法。 因此,像您所做的那样,将类工具声明为抽象,将startEnginestartEngine为抽象方法。 接下来,将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();
   }
}

通过Interface将Anonymouse内部类添加到barA方法中,因此您将需要实现foo()(功能接口)的方法。 它不会属于B类。

暂无
暂无

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

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