> On Jul 10, 2016, at 1:37 AM, Károly Lőrentey via swift-evolution 
> <swift-evolution@swift.org> wrote:
> 
> On 2016-07-09 04:39:01 +0000, Jordan Rose via swift-evolution said:
> 
>> I wanted to share a concrete use case that Daniel Dunbar relayed to me. He 
>> was working on a closed class hierarchy like the ones discussed here, where 
>> all of the subclasses are within a single module, but they are all public. 
>> The class also has a required initializer for dynamic construction, so that 
>> they could write something like this:
>> internal struct ModelContext { /*…*/ }
>> public class ModelBase {
>>   internal required init(context: ModelContext) { /*…*/ }
>>   // …
>> }
>> public class SimpleModel: ModelBase {
>>   internal required init(context: ModelContext) { /*…*/ }
>> }
>> public class MoreComplicatedModel: ModelBase { /*…*/ }
>> // (within some other type)
>> public func instantiateModelObject<Model: ModelBase>(_ type: Model) -> Model 
>> {
>>   return type.init(context: self.context)
>> }
>> That is, a public entry point calls a required initializer with an internal 
>> argument type. This is the only way to instantiate Model objects, and the 
>> internal context type doesn’t leak out into the public API.
>> Of course, Swift doesn’t allow this. If someone outside of the module 
>> subclasses ModelBase, there’s no way for them to provide the 
>> dynamically-dispatched 'init(context:)’, because they don’t have access to 
>> the internal ModelContext. The author of the library has to make the 
>> required initializers public, and either set the ModelContext separately or 
>> make it public as well. Even though no one outside the module should be 
>> using these APIs.
> 
> Can you remind us why does Swift need required initializers to have the same 
> access as the containing class?

Because without required initializers you can't do something like:

let cl: MyClass.Type = ...
let instance = cl.init(value: 0)

where MyClass has a required init(value: Int).

The issue here is that in order to be able to do this, subclasses that 
implement another initializer must implement this one as well - so it must be 
visible outside of the module if it is public.

> 
> Having only package-internal constructors in the public base class is the 
> usual pattern for exporting a sealed class hierarchy in some other languages, 
> like Java.
> 
> -- 
> Károly
> @lorentey
> 
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to