Why am I able to extend and override methods of NWConnection (which is a final class)?

The answer may be too obvious, and I may be asking a s*i*l*l**y* question. Please help me out understanding the issue.

As per Swift documentation, final classes can be extended, but you can not override the already declared methods etc. However, it seems like I am able to do that on NWConnection. I want to understand why it is possible. Here is my code.

Code Block
import Network
extension NWConnection {
// My new method
    func hello() {
        print("Hello")
    }
    func start(queue: DispatchQueue) {
        os_log("My Version is called")
//Hypothetical state modification
        self.stateUpdateHandler?(.setup)
    }
}

Yes, that's curious you can redefine start(queue: DispatchQueue).
The method itself is declared final:
Code Block
final func start(queue: DispatchQueue)

Even more surprising, if you write override func start(queue: DispatchQueue)
you get the compile error:
Method does not override any method from its superclass.

If I do same with another final class:

Code Block
final class MyUIVC : UIViewController {
}
extension MyUIVC {
func removeFromParent() {
}
}

I get the expected error:
Overriding declaration requires an 'override' keyword

Just as if start(queue: DispatchQueue) was not recognised in extension, but if I remove from extension, code still works, meaning start is recognised.


Swift namespaces your code based on the module. So, when you add a start(queue:) method to NWConnection, it’s completely different from the start(queue:) method added by the Network framework. You can think of the former as MyFunkyNetworkApp.start(queue:) and the latter as Network.start(queue:).

Notwithstanding this, I recommend that you not add methods or properties to NWConnection. This class was meant to be used as is, and hence the final modifier. If you need more functionality it’s better to get that via encapsulation. That is, create your own connection class that uses NWConnection via a has-a relationship and exports an abstraction layer that’s tailored to the specific needs of your higher-level code. My TCPTransports sample code shows the basic idea (although I’ve not updated it for NWConnection, alas).

And I strongly recommend that you not add methods or properties with the same signature as existing ones (like start(queue:)). That’s just gonna confuse the folks who end up maintaining your code down the line (and keep in mind that’s most likely to be Future You™).

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
@eskimo

I learned something here.

But why is it different with this:

Code Block
final class MyUIVC : UIViewController {
}
extension MyUIVC {
func removeFromParent() {
}
}


I get the error:
Overriding declaration requires an 'override' keyword

Discovered accidentally whilst writing unit tests. Thanks for the explanation and advice.

But why is it different with this:

Because UIViewController in an Objective-C object and -removeFromParent is an Objective-C method and Objective-C has no concept of namespaces.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
@eskimo
Waoouh
Why am I able to extend and override methods of NWConnection (which is a final class)?
 
 
Q