[英]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 B
的foo
方法更改为:
@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
方法。 因此,像您所做的那样,将类工具声明为抽象,将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();
}
}
通过Interface将Anonymouse内部类添加到barA方法中,因此您将需要实现foo()(功能接口)的方法。 它不会属于B类。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.