Is it possible to override deinit in Swift? [duplicate]
Asked Answered
H

1

5

When creating a subclass from another class, it is required to override the init() function, but you cannot override the deinit 'function'.

Is this possible in Swift?

Here is an example

class Foo {
    init(){
        print("Foo created")
    }

    deinit {
        print("Foo gone")
    }
}


class Bar: Foo {

    override init(){
        print("Bar created")
    }

    //Is not overwritten here
    deinit {
        print("Bar gone")
    }
}

Inside example viewcontroller

override func viewDidLoad() {
    super.viewDidLoad()

    var f: Foo?
    f = Foo()
    f = Bar()
    f = nil

}

Output

Foo created    //Foo object initialised - Foo init() called
Foo created    //Foo init() called before calling Bar init()? no call to superclass though..
Bar created    //Bar object initialised - Bar init() called
Foo gone       //Foo deinit called as Foo instance replaced by Bar instance
Bar gone       //Bar deinit called as Bar instance holds no references and is destroyed 
Foo gone       //Foo deinit called again as part of Bar object destruction?

To add to my original question about extending deinit:

In the example code it seems that overriding init() causes a call to the init() function of the superclass. Is this what is happening?

The same behaviour happens when the Bar instance is deinitialised. Is this also what is happening here?

Hass answered 28/10, 2016 at 11:52 Comment(3)
Related: Understand deinitialization and inheritance in swift language.Virtu
Oh wow strange I didn't find this :/ Thank you for linking!Hass
The console output is exactly what I would expect - the first "Foo gone" happens when the value of f gets overwritten by an instance of Bar. The deallocation of Bar calls the deinit method first on Bar, then it's superclass Foo (super class deinit is call automatically at the end of a deinit method).Argentous
R
9

deinit is not a normal method, it cannot be overriden. Every instance has one independent deinit handler for its class and all its superclasses.

Deinitializers are called automatically, just before instance deallocation takes place. You are not allowed to call a deinitializer yourself. Superclass deinitializers are inherited by their subclasses, and the superclass deinitializer is called automatically at the end of a subclass deinitializer implementation. Superclass deinitializers are always called, even if a subclass does not provide its own deinitializer.

There should be absolutely no reason to change anything the superclass is doing in its deinit.

Why is it different from init? In initializers you need to pass parameters, you also need to control the order of execution (some code before super.init(...), some code after super.init(...)). The deinitialization is an automatic process with a defined order of execution. Overriding could only introduce unnecessary problems.

Resonant answered 28/10, 2016 at 11:58 Comment(3)
That means there should not be any keyword deinit in my whole source code, right?Ornament
@SazzadHissainKhanq Not true. However, you cannot just from superclass deinit is doing from a subclass.Resonant
I add deinit all the time for debugging (mostly on my view controllers). In it, I usually just log messages to the console, set breakpoints, etc. to know "when" something is being deallocated (helps me track retain cycles). But as for "real" code needed in the final product, I have not needed deinit yet.Syneresis

© 2022 - 2024 — McMap. All rights reserved.