One-line Summary
Treat extension
s of a struct / class that are in the same file as the main declaration as if they are in the same block
Current Use
I use extension
a lot to clarify my code, separating the main declaration of a class/struct and its properties from the methods I define on it (a pattern I’ve seen in Swift a lot in Swift’s standard library, as well).
// MARK: -SimpleExample
class SimpleExample {
var foo: Int = 0
}
// MARK: methods
extension SimpleExample {
func increment() { foo += 1 }
}
The Problems
This is great, but there are some limitations on extension
that seem like missing compiler features and that make it harder to code cleanly:
⑴ You can’t override a method that was defined in an extension of a superclass in an subclass, so:
class SimpleChild : SimpleExample {
override open func increment() { foo += 2 }
}
gives the error Overriding non-@objc declarations from extensions is not supported
⑵ Related but slightly different, you also can’t override methods declared in a class in an extension to a subclass:
// MARK: -SimpleExample
class SimpleExample {
var foo: Int = 0
open func decrement() { foo -= 1 }
}
// MARK: -SimpleChild
class SimpleChild : SimpleExample {
}
// MARK: methods
extension SimpleChild {
override open func decrement() { foo -= 2 }
}
also gives the error Overriding non-@objc declarations from extensions is not supported
⑶ In a stretch goal, I’d like to see stored properties allowed in extensions (from the same file) as well:
class SimpleExample {
}
// MARK: methods
private extension SimpleExample {
var foo: Int
}
this currently gives the error Extensions must not contain stored properties
Simple, Hand-wavy Solution
The thought occurred to me that a quick way to achieve these goals for extensions in the same file as the main class/struct definition might be to have the compiler smoosh all extensions in the main file into a single big block. Obviously I’m no fancy compilerist so this could maybe be more difficult than I think, or maybe it has consequences I haven’t thought of, but I have run the idea past an Xcode person who thought it sounded reasonable.
Obviously it’d require a little more work than just, like, removing the words “extension” from the main file, because extensions can have different modifiers on them (public
, @objc
, etc), but my thought it is the compiler could just remember what modifiers were requested on the extension block and apply them to each individual item inside the block when forming the MEGA-BLOCK.
Effects on Existing Source / Binaries / ABI / API
It’s possible I haven’t thought through all the cases, but assuming I didn’t miss anything (or the things I missed can be worked around) this change is intended to be totally additive, and should have no effect on existing code / binaries.