Java: 方法只能由超类调用
Java: method only callable by superclass
我想阻止 class 调用它自己的方法。该方法只能由其超级 class.
调用
现在,我想不出有什么办法(干净利落地)实现这一点。但也许有人知道解决方案?
在代码中:
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 活动中的 onCreate(..)
)的问题。此处您覆盖了 paint
方法,但您永远不应调用它。
我认为您能做的最好的事情是向该方法添加文档以阐明它 永远不会 被子类显式调用或重新评估您的设计。
this answer 有一个很好的提示。
在您的 class (class 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
}
}
您可以将接口作为成员放入通过构造函数提供给它的超级 class 中。 child class 实现了该方法,但不能调用它,除非将其设为静态。
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的解释,这个解决方案可能就足够了。
我猜你不会关心 class 调用它的静态方法,因为它们只能影响很少使用的静态。匿名接口实现中的方法可以相互调用,但我想这没问题,因为你似乎只是想阻止其他人以某种不同的方式启动引擎。
有一种方法可以做到,但你需要使用Google Error Prone。这是 Java 编译器的扩展,旨在提供越来越多有用的警告和错误(类似于 FindBugs 和 PMD,但误报更少)。我只能推荐它,它已经帮助我们找到了一些错误。
具体来说,它包含一个注解@ForOverride
and an according compile-time check。此注释旨在用于子 class 和任何其他 class 不应调用的受保护方法,而只能用于定义 class.
所以使用
public abstract class A {
@ForOverride
protected abstract void foo();
private void barA() {
//do smth
foo();
}
}
完全可以达到你想要的效果。
您可以将 Error Prone 集成到大多数构建系统中,例如 Maven 和 Ant。当然,如果有人在没有 Error Prone 的情况下编译您的源代码(例如在 Eclipse 中),这将无济于事,但是在持续集成系统中使用它仍然可以让您发现此类问题。源代码仍然与常规 Java 编译器兼容(前提是 class 路径上有 error_prone_annotations.jar
),其他编译器将不会进行额外检查。
考虑到您的车辆和引擎场景,我认为您需要重新考虑一下您的设计。
您的交通工具可以是汽车、飞机等,但汽车、飞机……每个都有独立的引擎,因此 startEngine
方法不同。因此,像您所做的那样将您的 class 车辆声明为抽象的,并将 class startEngine
声明为抽象方法。接下来,subclass Vehicle 并在其中实现 startEngine
,现在您可以在 subclass 实例
上调用 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();
}
}
通过接口将 Anonymouse inner class 添加到 barA 方法,因此您需要为 foo() (功能接口)实现一个方法。它不会成为 Class B.
的一部分
我想阻止 class 调用它自己的方法。该方法只能由其超级 class.
调用现在,我想不出有什么办法(干净利落地)实现这一点。但也许有人知道解决方案?
在代码中:
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 活动中的 onCreate(..)
)的问题。此处您覆盖了 paint
方法,但您永远不应调用它。
我认为您能做的最好的事情是向该方法添加文档以阐明它 永远不会 被子类显式调用或重新评估您的设计。
this answer 有一个很好的提示。
在您的 class (class 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
}
}
您可以将接口作为成员放入通过构造函数提供给它的超级 class 中。 child class 实现了该方法,但不能调用它,除非将其设为静态。
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的解释,这个解决方案可能就足够了。 我猜你不会关心 class 调用它的静态方法,因为它们只能影响很少使用的静态。匿名接口实现中的方法可以相互调用,但我想这没问题,因为你似乎只是想阻止其他人以某种不同的方式启动引擎。
有一种方法可以做到,但你需要使用Google Error Prone。这是 Java 编译器的扩展,旨在提供越来越多有用的警告和错误(类似于 FindBugs 和 PMD,但误报更少)。我只能推荐它,它已经帮助我们找到了一些错误。
具体来说,它包含一个注解@ForOverride
and an according compile-time check。此注释旨在用于子 class 和任何其他 class 不应调用的受保护方法,而只能用于定义 class.
所以使用
public abstract class A {
@ForOverride
protected abstract void foo();
private void barA() {
//do smth
foo();
}
}
完全可以达到你想要的效果。
您可以将 Error Prone 集成到大多数构建系统中,例如 Maven 和 Ant。当然,如果有人在没有 Error Prone 的情况下编译您的源代码(例如在 Eclipse 中),这将无济于事,但是在持续集成系统中使用它仍然可以让您发现此类问题。源代码仍然与常规 Java 编译器兼容(前提是 class 路径上有 error_prone_annotations.jar
),其他编译器将不会进行额外检查。
考虑到您的车辆和引擎场景,我认为您需要重新考虑一下您的设计。
您的交通工具可以是汽车、飞机等,但汽车、飞机……每个都有独立的引擎,因此 startEngine
方法不同。因此,像您所做的那样将您的 class 车辆声明为抽象的,并将 class startEngine
声明为抽象方法。接下来,subclass Vehicle 并在其中实现 startEngine
,现在您可以在 subclass 实例
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();
}
}
通过接口将 Anonymouse inner class 添加到 barA 方法,因此您需要为 foo() (功能接口)实现一个方法。它不会成为 Class B.
的一部分