简体   繁体   English

Java,隐式调用重写方法

[英]Java, Call overridden method implicitly

Right now in some Java code I have something like this 现在在一些Java代码中,我有类似的东西

class A {
 void f() {

 }
 A() {
  f();
 }
}

class B extends A{
 @Override
 void f() {
  //do some stuff
  super.f();
 }
}

class C extends B {
 @Override
 void f() {
  //do some stuff
  super.f();
 }
}

I want to have f() called and then iterate upwards through each parent class, running the overridden f() . 我希望调用f()然后向上遍历每个父类,运行重写的f() I do this by calling super.f() explicitly, although I'd like to not have to do this. 我通过显式调用super.f()来做到这一点,尽管我不想这样做。

The reason why I do this is there post processing that must be done after the constructor in A is reached. 我这样做的原因是必须在到达A中的构造函数之后进行后处理。 And there is state in each class that much be properly init'd, which is why we have the upward trace of f() 's. 并且每个类中都有状态正确初始化,这就是为什么我们有f()的向上轨迹。

So the constructor of A is really 所以A的构造函数确实如此

A() {
  //init some state in a
  f(); //run f(), which will depend on the previous operation
}

If I do something like new C(); 如果我做new C(); I want Cf() called, then Bf() called, then Af() called 我想要调用Cf() ,然后调用Bf() ,然后调用Af()

Anyway, if there is a smarter way of doing this, I'm open to it. 无论如何,如果有更聪明的方法,我会接受它。

Calling non-final methods in a constructor is generally a bad idea - at the very least, I'd suggest you document it heavily . 在构造函数中调用非final方法通常是一个坏主意 - 至少,我建议你大量记录它。 Bear in mind that when f() is called, C's constructor won't have been called - and neither will any variable initializers. 请记住,当调用f()时,不会调用C的构造函数 - 也不会调用任何变量初始值设定项。 The object is only half-initialized, and so methods will need to be written very carefully. 该对象只是半初始化,因此需要非常仔细地编写方法。

There's no way of implicitly calling super.f() though in normal Java. 虽然在普通的Java中没有办法隐式调用super.f() Given the large warnings I'd be putting around that code, a single statement is far from the end of the world :) 鉴于我将围绕该代码发出大量警告,单一声明远离世界末日:)

If you want to verify that it's called, you could always check for the results of Af() in A's constructor immediately after the call - that will check that the call has reached the top level. 如果你想验证它是否被调用,你可以在调用后立即检查A的构造函数中的Af()结果 - 这将检查调用是否已达到顶级。

This may help you somewhat - it's a way to enforce that the child class calls the super; 这可能对你有所帮助 - 这是一种强制子类调用super的方法; this would help you detect developer mistakes where the implementer of a child class forgot to continue the call up the chain to super.f(): 这将帮助您检测开发人员错误,其中子类的实现者忘记继续调用链到super.f():

class A {
 boolean fDone;

 public final void f() {
  fDone = false;
  doF();
  if (!fDone) {
   throw new IllegalStateException("super.f() was not called");
  }
 }

 protected void doF() {
  //do some operation
  fDone = true;
 }
}

class B extends A {
 protected void doF() {
  //some operation, maybe repeat this pattern of using a flag to enforce super call
  super.doF();
 }
}

So, the child overrides doF(), but is required to call super.doF(); 所以,孩子会覆盖doF(),但是需要调用super.doF();

As far as I know, there's no way to do this. 据我所知,没有办法做到这一点。 AspectJ might do something similar to this, but then you'd have to tag it with an annotation, I suppose, which is hardly less work than just calling super.f() . AspectJ可能会做类似的事情,但是我想你必须用注释来标记它,这比调用super.f()少得多。 You need to signify that the superclass method is being called, because you need to have the ability to make that decision for each subclass separately - otherwise, you might have a subclass that doesn't want to delegate anything to the superclass at all - so the default is that you just put in the code. 您需要表示正在调用超类方法,因为您需要能够单独为每个子类做出决定 - 否则,您可能有一个子类根本不想将任何内容委托给超类 - 所以默认是您只需输入代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM