我想阻止一个类调用自己的方法。该方法只能由其超类调用。
现在,我想不出任何方法来实现这一目标(干净利落)。但也许有人知道解决方案?
在代码中:
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()来启动....这有什么意义吗?
答案 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类。