When NOT to call super() method when overriding?

When I make my own Android custom class, I extend its native class. Then when I want to override the base method, I always call super() method, just like I always do in onCreate, onStop, etc.

And I thought this is it, as from the very beginning Android team advised us to always call super on every method override.

But, in many books I can see that developers, more experienced than myself, often omit calling super and I really doubt they do it as a lack of knowledge. For example, look at this basic SAX parser class where super is omitted in startElement, characters and endElement:

public class SAXParser extends DefaultHandler{
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if(qName.equalsIgnoreCase("XXY")) {
//do something
}
}


public void characters(char[] ch, int start, int length) throws SAXException {
//do something
}


public void endElement(String uri, String localName, String qName) throws SAXException {
if(qName.equalsIgnoreCase("XXY")) {
//do something
}else () {
//do something
}
}
}

If you try to create any override method via Eclipse or any other IDE, super will always be created as a part of automated process.

This was just a simple example. Books are full of similar code.

How do they know when you must call super and when you can omit it calling?

PS. Do not bind to this specific example. It was just an example randomly picked from many examples.

(This may sound like a beginner question, but I am really confused.)

53201 次浏览

通过调用 super方法,您不是 重写方法的行为,您是 延伸它。

super的调用将执行所扩展的类为该方法定义的任何逻辑。考虑到在方法重写中调用 super的实现时可能很重要。例如:

public class A {
public void save() {
// Perform save logic
}
}


public class B extends A {
private Object b;
@Override
public void save() {
super.save(); // Performs the save logic for A
save(b); // Perform additional save logic
}
}

B.save()的调用将按照这个特定的顺序为 AB执行 save()逻辑。如果你不在 B.save()内部调用 super.save()A.save()就不会被调用。如果你在 save(b)之后调用 super.save()A.save()将在 B.save()之后有效地执行。

如果您想要 重写super的行为(也就是说,完全忽略它的实现并自己提供它) ,那么您不应该调用 super

在您提供的 SAXParser示例中,这些方法的 DefaultHandler实施是空的,因此子类可以重写它们并为这些方法提供行为。在此方法的 Javadoc中也指出了这一点。

public void startElement (String uri, String localName,
String qName, Attributes attributes) throws SAXException {
// no op
}

关于 IDE 生成的代码中的 super()默认调用,正如 @barsju在他的注释中指出的那样,在每个构造函数中都有一个对 super()的隐式调用(即使你没有在代码中写入它) ,这意味着在这种情况下,对 super的缺省构造函数的调用。IDE只是为您写下它,但是如果您删除它,它也会被调用。还要注意,在实现构造函数时,super()或其任何带参数的变体(即 super(x,y,z))只能被称为方法的 在最开始的时候

哈维给出了一个更好的答案。.但是您可能知道在重写方法中调用 super()super()会做什么... ... 它会显示您对默认行为所做的操作。.

例如:

onDraw()

重写时,视图类中的。.在说 super.onDraw ()之前先画一些东西,一旦视图完全绘制,它就会出现。.所以这里调用 super是必要的,因为 android 有一些非常重要的事情要做(比如 onCreate ())

但同时

onLongClick()

当您覆盖它时,您不想调用 super,因为它会打开一个对话框,其中包含 EditText 或任何其他类似视图的选项列表。.这是最基本的区别。.有时候你可以选择离开。.但对于其他方法,如 onCreate() , onStop(),你应该让操作系统处理它。.

我没有明白你的问题,但是如果你问为什么不调用 super方法:

调用 super方法是有原因的: 如果父类中没有零参数构造函数,那么就不可能为此创建一个子类,所以要么在父类中保留一个无参数构造函数,要么在子类构造函数的顶部定义 argument(how much argument constructor you have used in super class)调用语句。

我希望这有帮助。如果没有,让我知道。

你应该在头脑中做的测试是:

“我是否希望完成这个方法的所有功能,然后再做一些事情?”如果是,那么您想调用 super(),然后完成您的方法。对于诸如 onDraw()这样的“重要”方法来说也是如此,它在后台处理许多事情。

如果您只想要一些功能(就像您将覆盖的大多数方法一样) ,那么您可能不想调用 super()

他们怎么知道什么时候必须打电话给管理员,什么时候可以省略它的呼叫?

通常,如果一个特殊的 API 方法对底层框架上下文生命周期具有重要意义,那么它总是会在 API 文档中显式地说明和突出显示,比如 Activity.onCreate() API 文档。此外,如果 API 遵循健壮的设计,它应该抛出一些异常,以在项目编译时提醒使用者开发人员,并确保它不会在运行时生成错误。

如果 API 文档中没有明确说明这一点,那么使用者开发人员可以相当安全地假定在重写 API 方法时不必调用该方法。由使用者开发人员决定是使用默认行为(调用 super方法)还是完全覆盖它。

如果条件允许(我喜欢开源软件) ,用户开发人员总是可以查看 API 源代码,看看这个方法实际上是如何编写的。例如,查看 Activity.onCreate()DefaultHandler.startElement()来源

我实现了一个约束数组列表,如

public class ConstraintArrayList<T> extends ArrayList<T> {
ConstraintArrayList(Constraint<T> cons) {this.cons = cons;}
@Override
public boolean add(T element) {
if (cons.accept(element))
return super.add(element);
return false;
}
}

如果查看代码,它只是在实际让超类执行向列表添加元素的实际操作之前进行一些预检查。 这说明了方法重写的两个原因之一:

  1. Extensibility where you want to extend what the super class can do
  2. 通过多态性添加特定行为的具体性,比如在动物王国中常见的 move 语义示例中,鸟类移动(飞)和青蛙移动(跳)的方式对每个子类都是特定的。

对于那些想知道 Android 框架中哪些被覆盖的方法应该调用 super并发现这个问题的人来说——这里是2019-Android Studio 3 + 会在你需要的时候告诉你的最新提示。

enter image description here