117

当我制作自己的 Android 自定义类时,我extend是它的原生类。然后,当我想覆盖基本方法时,我总是调用super()方法,就像我总是在 , 等中所做的onCreate那样onStop

我认为就是这样,因为从一开始 Android 团队就建议我们始终调用super每个方法覆盖。

但是,在许多书中,我可以看到比我更有经验的开发人员经常忽略调用super,我真的怀疑他们这样做是因为缺乏知识。例如,看看这个基本的SAX解析器类,其中super省略了startElement,charactersendElement

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
        }
    }
}

如果您尝试通过 Eclipse 或任何其他 IDE 创建任何覆盖方法,super将始终作为自动化过程的一部分创建。

这只是一个简单的例子。书上到处都是类似的代码

他们怎么知道你什么时候必须打电话super,什么时候可以省略它?

PS。不要绑定到这个特定的例子。这只是从许多例子中随机挑选的一个例子。

(这听起来像是一个初学者的问题,但我真的很困惑。)

4

7 回答 7

149

通过调用该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()执行 和 的逻辑save()。如果你不在里面打电话,就不会被打电话。而如果你调用后,会有效地执行后。ABsuper.save()B.save()A.save()super.save()save(b)A.save()B.save()

如果你想覆盖 .supersuper

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

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

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

于 2012-04-20T10:53:19.687 回答
16

他们怎么知道何时必须调用 super 以及何时可以省略调用?

通常,如果一个特殊的 API 方法对底层框架上下文生命周期具有关键意义,它总是会在 API 文档中明确说明和突出显示,就像Activity.onCreate()API 文档一样。此外,如果 API 遵循稳健的设计,它应该在项目编译时抛出一些异常来提醒消费者开发人员,并确保它不会在运行时产生错误。

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

如果条件允许(我喜欢开源软件),消费者开发人员可以随时查看 API 源代码,了解该方法实际上是如何编写的。例如查看Activity.onCreate()DefaultHandler.startElement()

于 2012-04-20T11:53:06.217 回答
8

您应该在脑海中进行的测试是:

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

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

于 2012-04-20T11:24:18.337 回答
3

Well Xavi gave a better answer.. but you probably might be knowing what does super() do when called in a overridden method... it ads what have you done with the default behaviour..

e.g:

onDraw() 

method in view class when overridden.. you draw something before saying super.onDraw() it appears once the view is fully drawn.. so here calling super is necessary since android has some critically important things to do (like onCreate())

but at the same time

onLongClick()

when you override this you don't want to call super because it brings up a dialog with list of options for a EditText or any other similar view.. Thats the basic diff.. you have choice to leave it some times.. but for other methods like onCreate() , onStop() you should let the OS handle it..

于 2012-04-20T11:01:27.850 回答
3

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

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. 您想要扩展超类可以做什么的可扩展性
  2. 您希望通过多态性添加特定行为的特异性,例如在常见的动物界移动语义示例中,鸟类移动(飞行)和青蛙移动(跳跃)的方式特定于每个子类。
于 2012-04-24T18:31:45.620 回答
2

我没有清楚地了解您的问题,但是如果您问为什么不调用该super方法:

调用该方法是有原因的super:如果父类中没有零参数构造函数,则无法为此创建子类,因此您需要在父类中保留无参数构造函数,或者您需要在子类构造函数的顶部定义super()调用语句。argument(how much argument constructor you have used in super class)

我希望这有帮助。如果没有,请告诉我。

于 2012-04-20T11:07:33.013 回答
2

对于那些还想知道应该调用 Android 框架中哪些被覆盖的方法super并发现这个问题的人 - 这是 2019 年的当前提示 - Android Studio 3+ 会在您需要它时告诉您

在此处输入图像描述

于 2019-03-15T10:38:42.733 回答