I am attempting something very tricky using protocols provided by the standard library. Basically, in the following code, A and B are protocols from the standard library. I want to implement a "special" kind of B (named C in the following code), that is more clever than a regular B, and I want to make an implementation of A that can use either a B or a C, and that would use a default behaviour when provided with a B, and a smarter behaviour when provided with a C. However, C also by necessity uses Self.
This code is what I would like to do, but it does not work. It can be used as a playground for experimentation.
protocol A {
associatedtype T: B
func lookAt(thing: B) -> String
}
protocol B {
}
protocol C: B {
static var someThing: Self { get }
}
extension B {
func beSmart() -> String { return "I am a stupid B" }
}
extension C {
func beSmart() -> String { return "I am a clever C" }
}
struct AImplementation<T: B> {
func lookAt(thing: T) -> String {
return "A \(String(describing: T.self)) says: \(thing.beSmart())"
}
}
struct BImplementation: B {
}
struct CImplementation: C {
static let someThing = CImplementation()
}
let AimplWithB = AImplementation<BImplementation>()
AimplWithB.lookAt(thing: BImplementation())
let AimplWithC = AImplementation<CImplementation>()
AimplWithC.lookAt(thing: CImplementation())
This should result in the texts "A BImplementation says: I am a stupid B" and "A CImplementation says: I am a clever C".
However, it will currently say "A BImplementation says: I am a stupid B" and "A CImplementation says: I am a stupid B".
The correct type is available at the call to beSmart()
, but apparently Swift will not figure out which beSmart()
to call. Is there some way to make this code work as intended, without touching protocols A or B, and letting C use Self?