So what I want to do is use the generic type of an interface to constrain another generic interface.
(pseudo code)
interface SomeInterface<T> {
T someMethod();
}
interface SomeOtherInterface<T> {
void someOtherMethod(SomeInterface<T> someImplementation);
}
SomeOtherInterface<SomeType> someOtherImplementation = new SomeOtherImplementation();
Now the call to someOtherMethod will constrain the parameter to the same generic type as the implementation.
Is this possible using protocols and if so...how?
I have tried a combination of associated types and generic method signatures but I don't quite get the same results.
Thanks, great answer!! BUT...
The problem is on the last line of my example. I can't figure out how to type hint for the protocol with an associated type. I don't want to limit my self to a specific implementation.
You can write type erasers. Typically you would name a type eraser by putting Any on the front of the protocol name. Since Factory has no generic methods, you can use a simpler technique for AnyFactory.
struct AnyFactory<Product>: Factory {
init<F: Factory>(_ wrapped: F) where F.Product == Product {
_make = wrapped.make
}
func make() -> Product { return _make() }
private let _make: () -> Product
}
struct AnyConsumer<Product>: Consumer {
init<C: Consumer>(_ wrapped: C) where C.Product == Product {
box = Box(wrapped)
}
func consumeOutput<F>(of factory: F) where F : Factory, Product == F.Product {
return box.consumeOutput(of: factory)
}
private let box: BoxBase
private class BoxBase {
func consumeOutput<F: Factory>(of factory: F) where F.Product == Product {
fatalError()
}
}
private class Box<Wrapped: Consumer>: BoxBase where Wrapped.Product == Product {
init(_ wrapped: Wrapped) { self.wrapped = wrapped }
let wrapped: Wrapped
override func consumeOutput<F>(of factory: F) where Product == F.Product, F : Factory {
return wrapped.consumeOutput(of: factory)
}
}
}