Created
November 7, 2019 15:07
-
-
Save inamiy/de70f5b107af7b4c6d64c317c7d19930 to your computer and use it in GitHub Desktop.
Private conformance to public protocol without making internal members / methods public.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Private Conformance (Generic Manifesto) | |
// https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md#private-conformances | |
// | |
// > Right now, a protocol conformance can be no less visible than the minimum of the conforming type's access and the protocol's access. | |
// > Therefore, a public type conforming to a public protocol must provide the conformance publicly. | |
// > The main problem with private conformances is the interaction with dynamic casting | |
public protocol PublicProtocol { | |
var foo: String { get } | |
} | |
// OK | |
internal struct Struct: PublicProtocol { | |
internal var foo: String = "" | |
} | |
// ERROR: Property 'foo' must be declared public because it matches a requirement in public protocol 'PublicProtocol' | |
//public struct PublicStruct: PublicProtocol { | |
// fileprivate var foo: String = "" | |
//} | |
// ERROR: This doesn' work too. | |
//internal extension PublicStruct: PublicProtocol { | |
// var foo: String { "" } | |
//} | |
// Goal: always keep `foo` as private, but conform to `PublicProtocol` for internal usage only. | |
public struct PublicStruct { | |
internal var foo: String = "" | |
} | |
// Solution: | |
// Add **internal proxy** that conforms to `PublicProtocol` instead. | |
// Inside the same module, use this type to gain `PublicProtocol` behavior. | |
// For the outside of the module, `PublicStruct` is the only public as usual. | |
internal struct PrivateProxy: PublicProtocol { | |
internal var inner: PublicStruct | |
// Forward all protocol requirements... | |
internal var foo: String { // But this is still exposing `foo`... | |
inner.foo | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment