我在使用 super 和覆盖方面遇到了问题。基本上,扩展 A
的类 B
有一个用于类当前状态的 setter 。在 setter 内部,根据当前状态的值,可以执行不同的事件。
在 B
的 setter 中发生的第一件事是调用 super
以便 A
的 setter 可以启动一般事件.然后控件返回到 B
的 setter,如果需要我可以在其中执行特定事件。
当 A
执行调用 setter 的事件时,问题就来了,因此它可以在返回到 B
之前进入多个深度。
下面的代码说明了我在说什么(很正常,但那是无关紧要的):
class A
{
public int num = 0;
public void setFoo( int i )
{
println "A: $i";
num = i + 1;
// what's actually happening, is that in the setter, depending
// on the value, an event can be executed, which will in turn
// call setFoo() on the class. this is just the equivalet
if( i < 3 )
this.setFoo( num );
}
}
class B extends A
{
public void setFoo( int i )
{
println "B: $i - num $num";
super.setFoo( i );
println "After super for $i - num: $num";
}
}
def B = new B();
B.foo = 0;
这导致输出:
B: 0 - num 0
A: 0
B: 1 - num 1
A: 1
B: 2 - num 2
A: 2
B: 3 - num 3
A: 3
After super for 3 - num: 4
After super for 2 - num: 4
After super for 1 - num: 4
After super for 0 - num: 4
当我在调用 super
(“After super for...”)后回到 B
时,num
的值是总是一样的,这意味着它与我在 B
中尝试做的事情有关(即启动特定事件)。
架构的一些要点:
- “为什么不在
B
的 setter 中使用i
而不是num
”? - 这只是显示问题的最简单示例 - 我的代码中实际发生的情况不同,只是同一个问题。在我的例子中,我可以访问num
,而不是i
。即使我重写了它的一部分以通过i
,类的状态也会继续(由于基类) - 这是一个服务器环境,所以我无法访问帧循环或类似的东西。它是基于事件的。
- 应该可以异步执行事件,或者将事件设置为稍后安排,但这需要大量关于事件将在何时何地使用的预先知识,这打破了事件的全部意义第一名
我正在寻找的是一种根据类的状态启动事件的方法,但如果是的话,它是否会在 super
返回后发生(同时仍在为基类工作)有任何意义。
想法?
编辑
为了更好地了解我正在使用的代码(根据 Don 关于使用回调的建议),这里是我所拥有的代码的简化版本。 (如果你想运行它,你可以将它复制到 http://groovyconsole.appspot.com/ ):
// A is our base class
class A{
public int currentState= 0;
public void setCurrentState( int i )
{
this.currentState = i;
this._onStateChanged();
}
protected void _onStateChanged()
{
println "The state in A is $currentState";
// depending on the state launch some events.
// these can changed the current state of
// B
if( this.currentState == 0 )
{
def event = new MyEvent( this );
event.execute();
}
}
}
// B is a more specific version of A
class B extends A
{
protected void _onStateChanged()
{
println "The state in B is $currentState";
super._onStateChanged();
println "The state in B afterwards is $currentState";
// launch specific events based on the current state
if( this.currentState == 0 )
println "Launch a specific event!";
}
}
// simple event class that can change the status of B
class MyEvent
{
private B b = null;
public MyEvent( B b )
{
this.b = b;
}
public void execute()
{
// do some stuff
b.currentState++;
}
}
// program start
def b = new B();
b.currentState = 0;
B
必须调用 super
,因为在某些状态下我需要一个基本的 plus 特定事件。基本事件通常用于设置程序状态,而特定事件用于响应。
在这个例子中,我的输出是:
The state in B is 0
The state in A is 0
The state in B is 1
The state in A is 1
The state in B afterwards is 1
The state in B afterwards is 1
即B 永远不会对状态为 0 使用react
编辑
如果我将 B
中的 super()
调用更改为 _onStateChanged()
的末尾而不是开始,这将给出它有机会在状态改变之前对状态使用react。这是解决这个问题的简单方法,还是错误的?
编辑 所以我想到了这个(同样,您可以将它复制到 groovy console appspot 站点):
// A is our base class
class A{
public int currentState = 0;
public int nextState = 0;
public boolean canChange = true;
public void setCurrentState( int i )
{
if( this.canChange )
{
this.currentState = i;
this._onStateChanged();
}
else
this.nextState = i;
}
protected void _onStateChanged()
{
println "The state in A is $currentState";
// depending on the state launch some events.
// these can changed the current state of
// B
if( this.currentState == 0 )
{
def event = new MyEvent( this );
event.execute();
}
}
}
// B is a more specific version of A
class B extends A
{
protected void _onStateChanged()
{
this.canChange = false;
println "The state in B is $currentState";
super._onStateChanged();
println "The state in B afterwards is $currentState";
// launch specific events based on the current state
if( this.currentState == 0 )
println "Launch a specific event!";
this.canChange = true;
if( this.nextState != 0 )
{
int state = this.nextState;
this.nextState = 0;
this.currentState = state;
}
}
}
// simple event class that can change the status of B
class MyEvent
{
private B b = null;
public MyEvent( B b )
{
this.b = b;
}
public void execute()
{
// do some stuff
b.currentState++;
}
}
// program start
def b = new B();
b.currentState = 0;
它给了我想要的输出:
The state in B is 0
The state in A is 0
The state in B afterwards is 0
Launch a specific event!
The state in B is 1
The state in A is 1
The state in B afterwards is 1
但是有点丑。更好的方法?
最佳答案
从根本上说,A.setFoo
被破坏了
class A
{
public int num = 0;
public void setFoo( int i )
{
println "A: $i";
num = i + 1;
// what's actually happening, is that in the setter, depending
// on the value, an event can be executed, which will in turn
// call setFoo() on the class. this is just the equivalet
if( i < 3 )
this.setFoo( num );
}
}
因为new A().setFoo(2)
(举例)会造成栈溢出。像下面这样的东西可能是一个更好的设计
abstract class A
{
public int num = 0;
abstract void setFooCallback(int i)
public final void setFoo( int i )
{
println "A: $i";
num = i + 1;
// what's actually happening, is that in the setter, depending
// on the value, an event can be executed, which will in turn
// call setFoo() on the class. this is just the equivalet
if( i < 3 )
this.setFooCallback( num );
}
}
class B extends A
{
public void setFooCallback( int i )
{
// Implement me to launch custom events or whatever
// If you call setFoo in here you'll get a stack overflow
}
}
如果您需要实例化 A 的实例,只需删除 abstract
修饰符并将 setFooCallback
更改为:
void setFooCallback(int i) { // default implementation does nothing }
仅供引用,我认为以上是模板(方法)模式的示例
关于java - super 和覆盖的问题 - 更好的方法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6650512/