0

TL;DR: Why can you override NSViewController methods in a subclass using an extension when the Swift Programming Guide implies that extensions cannot be used to override functions?

In the Swift Programming Guide - Extensions section, it states:

Extensions can add new functionality to a type, but they cannot override existing functionality.

However, I routinely override NSViewController in an extension on my subclass. Example:

class ViewController : NSViewController {}

extension ViewController {
  
  // This is legal and does not generate a compiler error. 
  // The method viewDidLoad() is declared in NSViewController itself.
  override func viewDidLoad() {
    super.viewDidLoad()
  }

  // This is legal and also does not generate a compiler error.
  // The method addChild() is declared in an extension on NSViewController.
  //
  override func addChild(_ childViewController: NSViewController) {
    super.addChild(childViewController)
  }
}

If you look at the Swift generated interface for NSViewController, the method addChild is defined in an extension. So the extension in my subclass is overriding a method defined in an extension in its parent class.

Presumably this is allowed because NSViewController is an Objective-C class. Attempting to use the same pattern in a Swift-only class yields a compiler error.

But I've found very little documentation on this behaviour and was curious:

  • What are the rules for overriding a method in an Objective-C class?
  • viewDidLoad, viewWillAppear and several other NSViewController methods are not defined in an extension whereas most others are. Does it matter if my subclass overrides them in an extension or not?
  • I assume the @objc decorator is playing an important role in this. Is there any documentation out there describing how @objc affects override such that it us allowed in extensions? Or is this behaviour supported because NSViewController is ultimately an NSObject?

macOS 10.15 Beta 5, Xcode 11 Beta 5

Community
  • 1
  • 1
kennyc
  • 5,490
  • 5
  • 34
  • 57
  • I think this is (partially?) a duplicate of [this question](https://stackoverflow.com/questions/38213286/overriding-methods-in-swift-extensions). To quote from the first answer: "The compiler is allowing you to override in the extension for compatibility with Objective-C. But it's actually violating the language directive." [This question](https://stackoverflow.com/questions/50151102/objc-keyword-extension-subclass-behaviour?noredirect=1&lq=1) is related too. – Daniel Aug 12 '19 at 15:16
  • That first question is indeed related, thank you. I still find it quite surprising that the general consensus is "It works, it shouldn't, but it does, you shouldn't do it, but if you do it will work." I see `UIViewController` and `NSViewController` methods being overriden in extensions throughout plenty of sample code. – kennyc Aug 12 '19 at 15:49
  • Rules are AFAIK the same in Swift as in ObjC: [Overriding methods using categories in ObjC](https://stackoverflow.com/q/5272451) This is some distance down the road to UB. – jscs Aug 12 '19 at 17:21

0 Answers0