Java:强制基础 class 使用基础 class 方法而不是覆盖方法
Java: Force base class to use base class method instead of overriden method
我有一个 Base class 方法,我想在 Derived class 中覆盖它。
只要从 "outside" 或派生的 class 访问同名方法,就应调用派生的 class 方法。从基础 class 内部访问方法时,我希望使用基础 class 方法。考虑以下代码:
public class TestBaseMethod
{
static class Basic {
public Basic()
{
Basic.this.doSomething(); // <<---- This should call Basic version
}
public void doSomething()
{
System.out.println("Doing something old");
}
}
static class Derived extends Basic {
Object ressource = new Object();
@Override
public void doSomething()
{
System.out.println("Doing something completely new");
// ressource.toString(); // <<---- explosion
}
}
public static void main(String[] args)
{
Basic d = new Derived();
System.out.println("-------------------------------");
d.doSomething(); // <<---- This should call Derived version
}
}
我想要以下输出:
Doing something old
-------------------------------
Doing something completely new
但是它产生了这个输出:
Doing something completely new
-------------------------------
Doing something completely new
我认为在 Basic.this.doSomething();
中明确说明基 class 名称应该可以做到这一点,但显然不是。
显然,我可以在 Derived class 而不是 Deriving 中声明一个 Basic 类型的变量,但这种做法违背了 Derived class "is-a" Basic class 并且会迫使我编写 oneline-redirection 方法来获得相同的接口。
这就是我想要这样做的原因:
在编写基础 classes 时,我想使用可以保证在基础 class 内部使用的方法,因为我不想派生 classes 干扰基础 class 内部结构。对我来说,从封装的角度来看这是有道理的,但也许我错了?
Basic#doSomething()
方法可以从 Basic()
构造函数中调用。
如果 Derived#doSomething()
方法使用来自 Derived
的资源,那么这些资源将仅在 Derived
构建后可用。
然而: Derived
构造在 superclass 构造之后完成,这意味着当构造 Derived
时, Derived#doSomething()
在 Basic()
构造函数中被调用,它将访问未初始化的数据。
有办法解决这个问题吗?
从构造函数调用真正的方法是一种不好的做法,更多信息可以在这里找到:On invoking overridable method from constructors
至于强制调用基础 class 方法 - 这是不可能的。
在 Basic 中为 doSomething 创建一个内部方法并直接调用它:
static class Basic {
public Basic()
{
doSomethingImpl();
}
public void doSomething()
{
doSomethingImpl();
}
private void doSomethingImpl()
{
System.out.println("Doing something old");
}
}
从设计的角度来看,你想要做的是不好的。一个好的设计是声明两个单独的方法,一个可覆盖,另一个不可覆盖(final 或 private)。
我有一个 Base class 方法,我想在 Derived class 中覆盖它。
只要从 "outside" 或派生的 class 访问同名方法,就应调用派生的 class 方法。从基础 class 内部访问方法时,我希望使用基础 class 方法。考虑以下代码:
public class TestBaseMethod
{
static class Basic {
public Basic()
{
Basic.this.doSomething(); // <<---- This should call Basic version
}
public void doSomething()
{
System.out.println("Doing something old");
}
}
static class Derived extends Basic {
Object ressource = new Object();
@Override
public void doSomething()
{
System.out.println("Doing something completely new");
// ressource.toString(); // <<---- explosion
}
}
public static void main(String[] args)
{
Basic d = new Derived();
System.out.println("-------------------------------");
d.doSomething(); // <<---- This should call Derived version
}
}
我想要以下输出:
Doing something old
-------------------------------
Doing something completely new
但是它产生了这个输出:
Doing something completely new
-------------------------------
Doing something completely new
我认为在 Basic.this.doSomething();
中明确说明基 class 名称应该可以做到这一点,但显然不是。
显然,我可以在 Derived class 而不是 Deriving 中声明一个 Basic 类型的变量,但这种做法违背了 Derived class "is-a" Basic class 并且会迫使我编写 oneline-redirection 方法来获得相同的接口。
这就是我想要这样做的原因:
在编写基础 classes 时,我想使用可以保证在基础 class 内部使用的方法,因为我不想派生 classes 干扰基础 class 内部结构。对我来说,从封装的角度来看这是有道理的,但也许我错了?
Basic#doSomething()
方法可以从 Basic()
构造函数中调用。
如果 Derived#doSomething()
方法使用来自 Derived
的资源,那么这些资源将仅在 Derived
构建后可用。
然而: Derived
构造在 superclass 构造之后完成,这意味着当构造 Derived
时, Derived#doSomething()
在 Basic()
构造函数中被调用,它将访问未初始化的数据。
有办法解决这个问题吗?
从构造函数调用真正的方法是一种不好的做法,更多信息可以在这里找到:On invoking overridable method from constructors
至于强制调用基础 class 方法 - 这是不可能的。
在 Basic 中为 doSomething 创建一个内部方法并直接调用它:
static class Basic {
public Basic()
{
doSomethingImpl();
}
public void doSomething()
{
doSomethingImpl();
}
private void doSomethingImpl()
{
System.out.println("Doing something old");
}
}
从设计的角度来看,你想要做的是不好的。一个好的设计是声明两个单独的方法,一个可覆盖,另一个不可覆盖(final 或 private)。