何时不调用 super() 方法时重写?

2022-08-31 09:01:08

当我创建自己的Android自定义类时,我是本机类。然后,当我想重写基方法时,我总是调用方法,就像我总是在 、等中所做的那样。extendsuper()onCreateonStop

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

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

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.不要绑定到此特定示例。这只是从许多例子中随机挑选的一个例子。

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


答案 1

通过调用该方法,您不会重写该方法的行为,而是在扩展它。super

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

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

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

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

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


答案 2

他们怎么知道什么时候你必须调用超级,什么时候你可以省略它调用?

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

如果 API 文档中未明确说明这一点,则使用者开发人员可以非常安全地假设 API 方法在重写时不是强制调用的。使用者开发人员可以决定是使用默认行为(调用方法)还是完全重写它。super

如果条件允许(我喜欢开源软件),消费者开发人员可以随时查看API源代码,并查看该方法实际上是如何在引擎盖下编写的。例如,请查看Active.onCreate() sourceDefaultHandler.startElement()source


推荐