Ability to mark a class as publicly final while remaining internally non-final


(Matt Comi) #1

Consider a public class that conforms to an internal protocol that has an initializer requirement:

internal class SomeInternalClass { }

internal protocol SomeInternalProtocol {
  init(parameter: SomeInternalClass)
}

public class SomePublicClass: SomeInternalProtocol {
  // compiler error: initializer requirement ‘init(parameter:)’ can only be satisfied by a `required` initializer in non-final class ‘SomePublicClass’
  init(parameter: SomeInternalClass) { }
}

To resolve this error, init(parameter:) must be made public required, or SomePublicClass must be made final.

If init(parameter:) were made public required, it would expose the module's internal structure; SomeInternalClass would need to be made public also. This makes sense, of course; if SomePublicClass is public and non-final, it may be subclassed outside the module and any subclass would need to know about init(parameter:) in order to remain conformant to SomeInternalProtocol.

Alternatively, If SomePublicClass were made final, it could not be subclassed outside the module and thus, SomeInternalClass would not need to be exposed, but subclassing SomePublicClass within the module would also be impossible also.

I propose that it should be possible to mark a class as publicly final while remaining internally non-final. This would resolve both issues: SomeInternalClass can remain internal, and SomePublicClass can be subclassed within the module.