Skip to content

Instantly share code, notes, and snippets.

@reitzig
Last active March 1, 2017 10:47
Show Gist options
  • Save reitzig/e2f2c568b0723a68a347509083d60d89 to your computer and use it in GitHub Desktop.
Save reitzig/e2f2c568b0723a68a347509083d60d89 to your computer and use it in GitHub Desktop.
Constructing new values in a public function using initializers from an internal protocol
// Using Swift 3.0.1
// see also http://stackoverflow.com/q/42514600/539599
import Foundation
public protocol P {
var foo: Int { get }
}
internal protocol Q {
init(from: MyDataRepresentation)
}
internal typealias MyDataRepresentation = [String]
public struct S: P, Q {
public var foo: Int = 0
public init() {}
init(from: MyDataRepresentation) {
precondition(from.count > 0)
self.foo = Int(from[0])!
}
}
public struct T: P, Q {
public var foo: Int = 77
public init() {}
init(from: MyDataRepresentation) {
precondition(from.count > 0)
self.foo = Int(from[0])! * 2
}
}
// A renegade struct, maybe declared by outsiders
public struct U: P {
public var foo = 99
}
public class ProviderOfThings {
// Note how the methods do not (and may not!) expose internal API!
public static func map<T: P>(before: T) -> T? {
guard let beforeQ = before as? Q else {
return nil
}
return type(of: beforeQ).init(from: [String(before.foo + 1)]) as! T
}
public static func make<T: P>() -> T? {
guard T.self is Q.Type else {
return nil
}
return (T.self as! Q.Type).init(from: ["0"]) as! T
}
}
print(ProviderOfThings.map(before: myS))
// Expected: 1
print(ProviderOfThings.map(before: myT))
// Expected: 156
print(ProviderOfThings.map(before: myU))
// Expected: nil
let anotherS: S? = ProviderOfThings.make()
let anotherT: T? = ProviderOfThings.make()
let anotherU: U? = ProviderOfThings.make()
print("\(anotherS) -- \(anotherT) -- \(anotherU)")
// Expected: 1 -- 2 -- nil
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment