Last active
March 1, 2017 10:47
-
-
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
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
// 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 | |
} | |
} |
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
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