In a non-final class, a designated initializer can be called as part of a super.init delegation from a derived class. The "self" value is going to be a partially initialized instance of the derived class in this case, with the derived class's stored properties already initialized but nothing else. It wouldn't make sense to replace "self" with a fully initialized instance while it is in this state.
I have a prototype implementation here: [awaiting evolution] Allow convenience initializers to reassign self. by jckarter ยท Pull Request #19311 ยท apple/swift ยท GitHub
I am quite glad there is movement on this! It will definitely help swift-corelibs-foundation be not only more efficient but also work more in-line with the objc implementation for factory style initializers.
Per the designated initializer case it would be nice to allow this if and only if the type of self == the type that was allocated (e.g. a runtime check for the non-final case that Slava brought up). That change would allow SCLF to implement every case that should be a factory pattern.
Supporting that would require some fancier control-flow-sensitive analysis than we current do for definite initialization, since we'd have to ensure that a self = assignment only occurred in a context where it was known that Self == ConcreteClass. Maybe if we a type-refining cast feature like like what @grego proposes here we could confine self-assignments in a designated initializer to if <Self == C> condition blocks.
Slightly off-topic, but would it make sense to add a similar feature to Swift like instancetype from Objective-C. That type should bound the currently unconstrained Self to something that you just mentioned Self == C. This is really a missing feature for factory initializer in the context of designated initializers and it would also allow new and safe generic patterns to be expressed in Swift. What do you think @Joe_Groff?
Self is instancetype. Factory initializers are interesting in that they do not always return instancetype.
What's the update on this proposal? Anything blocking it?
I haven't had time to finish the implementation. There are still a few issues with the implementation in [awaiting evolution] Allow convenience initializers to reassign self. by jckarter ยท Pull Request #19311 ยท apple/swift ยท GitHub that need to be fixed to get the tests passing.
This would be particularly helpful for classes that represent Core Data entities, as it would allow you to define initializers that use NSFetchRequests to retrieve information.
I guess I'm way too impatient, but I'd love to see this feature so I was just wondering when it will be merged ![]()
Me too!
The implementation needs to be completed for the feature to be considered for review. I got a start in Proposal: Allow convenience inits to assign `self` by jckarter ยท Pull Request #910 ยท apple/swift-evolution ยท GitHub but there is more work to be done.
Just needed this one today ![]()
import Contacts
extension CNPostalAddress {
convenience init(_ apiAddress: API.Address) {
let address = CNMutablePostalAddress()
address.city = ...
self = address // Cannot assign to value: 'self' is immutable
}
}
Exactly why I searched and found this old thread today ![]()