[swift-evolution] [Manifesto] Completing Generics
Brent Royal-Gordon
brent at architechies.com
Wed Aug 3 04:09:50 CDT 2016
> On Aug 2, 2016, at 7:58 AM, Patrick Lind via swift-evolution <swift-evolution at swift.org> wrote:
>
> http://stackoverflow.com/questions/38619660/is-it-possible-to-pass-generic-protocols-into-a-constructor-for-proper-dependenc
I *think* that the specific feature you're looking for here is usually called "enhanced existentials". This would have a different syntax—something like `RepositoryProtocol where Object == Zombie`—but would do basically the same thing.
The way to work around this in Swift 2 or 3 is to manually write a type-erasing wrapper:
// Effectively a constructor of AnyRepository.
public func anyRepository<Repository: RepositoryProtocol>(_ repository: Repository) -> AnyRepository<Repository.Object> {
// Don't double-wrap
if let repo = repository as? AnyRepository<Repository.Object> {
return repo
}
return ConcreteAnyRepository(repository: repository)
}
// This is the public face of the wrapper. It's actually abstract. Since it doesn't have the
// RepositoryProtocol as a parameter, it "erases" the repository's type.
public class AnyRepository<Object>: RepositoryProtocol {
private init() {}
public var items: Array<Object> {
get { fatalError("abstract") }
set { fatalError("abstract") }
}
public func insert(_ object: Object) {
fatalError("abstract")
}
public func deleteAll() {
fatalError("abstract")
}
}
// All instances of AnyRepository will actually belong to this concrete subclass, which
// *does* have the specific RepositoryProtocol as a parameter.
private class ConcreteAnyRepository<Repository: RepositoryProtocol>: AnyRepository<Repository.Object> {
private let repository: Repository
override var items: Array<Object> {
get { return repository.items }
set { repository.items = newValue }
}
override func insert(_ object: Object) {
repository.insert(object)
}
override func deleteAll() {
repository.deleteAll()
}
}
And then your ZombieServiceProtocol can look like:
protocol ZombieServiceProtocol {
func fetchZombies()
var zombieRepository: AnyRepository<Zombie> { get set }
}
--
Brent Royal-Gordon
Architechies
More information about the swift-evolution
mailing list