[swift-evolution] Proposal - Allow properties in Extensions

Matthew Johnson matthew at anandabits.com
Thu Dec 24 14:10:35 CST 2015


> On Dec 24, 2015, at 2:05 PM, John McCall <rjmccall at apple.com> wrote:
> 
>> On Dec 24, 2015, at 11:48 AM, Matthew Johnson <matthew at anandabits.com> wrote:
>>> On Dec 24, 2015, at 1:31 PM, John McCall <rjmccall at apple.com> wrote:
>>> 
>>> 
>>>> On Dec 23, 2015, at 10:51 AM, Matthew Johnson <matthew at anandabits.com> wrote:
>>>> 
>>>> 
>>>>>> On Dec 23, 2015, at 12:50 PM, John McCall via swift-evolution <swift-evolution at swift.org> wrote:
>>>>>> 
>>>>>> On Dec 23, 2015, at 7:05 AM, Paul Cantrell <cantrell at pobox.com> wrote:
>>>>>>> On Dec 22, 2015, at 10:45 PM, John McCall via swift-evolution <swift-evolution at swift.org> wrote:
>>>>>>> 
>>>>>>> when you stuff a lot of functionality into a single class in most OO languages, there’s no real way to enforce its division into subsystems, because every method has direct access to every property and every other method.  In contrast, in Swift you can divide that class into distinct components with their own interface, state, and invariants, essentially making each component as good as its own type as far as encapsulation goes.
>>>>>> 
>>>>>> Can you elaborate on this, John? Extensions and protocols in Swift today still don’t solve the problem that shared _private_ class state has to be centralized. Or were you speaking as if this “properties in extensions” proposal were already implemented?
>>>>> 
>>>>> Yes, that’s right.  I’m explaining why I think it makes sense to limit stored instance properties in extensions to class types: especially with some solution for private initialization of extensions, they enable intra-class encapsulation in a way that matters for classes and not really for other types.
>>>> 
>>>> How would private initialization of extensions work?
>>> 
>>> Just spit-balling, but something like:
>>> 
>>> class A {
>>>  init(numbers: [Int]) {
>>>     // Definitive initialization requires initialization of all the extensions
>>>     // in the module that declare partial inits before the call to super.init.
>>>     self.init(counts: numbers)
>>> 
>>>     // Okay, now we super.init.
>>>     super.init()
>>> 
>>>     // Fully initialized now.
>>>   }
>>> }
>>> 
>>> extension A {
>>>  let counts: [Int]
>>>  partial init(counts: [Int]) {
>>>    // Definitive initialization requires a partial init to initialize all the stored properties
>>>    // in this extension.  This all happens prior to the complete initialization of self,
>>>    // so unlike a normal init, there is no point in this initializer when unrestricted
>>>    // use of self is allowed.  If that’s required, it can be done with an ordinary method
>>>    // call.
>>>    //
>>>    // To start, partial initializers would not be allowed to use properties from other
>>>    // extensions or the main class.  We can consider ways to lift that restriction later.
>>> 
>>>    self.counts = counts
>>>  }
>>> }
>> 
>> I'm really not sure I like this very much.  It seems to be exactly what I was concerned about.  The primary advantage this seems to provide is encapsulation for the extension.  Unfortunately it also means the extension has a ripple effect requiring initializers elsewhere in the project to be updated.  This doesn't feel like an "extension" as it actually seems to be pretty invasive.  It gives me an uneasy feeling at first glance.
> 
> Any proposal which allows stored properties with non-default initialization to be added in an extension is going to require source changes to the main class initializer(s).  My suggestion of partial inits achieves that without breaking encapsulation, which in my judgment would not be acceptable.  You could also just require all stored properties in extensions to have a default initializer, which is the rule we’d be forced to use outside the module anyway.  These are your options if you actually care about this feature.

Understood.  I’m still trying to asses how I feel about the idea in general.  There are certainly advantages, but there are also drawbacks, particularly when the stored properties aren’t required to have defaults.

Matthew


More information about the swift-evolution mailing list