I have recently come across a similar need and thought of a naive solution:
protocol Foo {
func x() -> Int
}
extension Foo {
func x() -> Int {
return 44
}
}
struct Bar: Foo {
func x() -> Int {
if something { return 0 }
// Otherwise fallback to default implementation:
return Foo.x(self)()
}
}
Which in theory should work, but seems not to be possible due to [SR-75] Referencing a protocol function crashes the compiler · Issue #42697 · apple/swift · GitHub.
Alternatively, this could be something like self.Foo.x(), but that seems kind of like C++.
The real-world motivation for this is here:
protocol FilterBase {
func isFooVisible(_ foo: Foo) -> Bool
func filteredFoos(_ foos: [Foo]) -> [Foo]
}
The default implementation of filteredFoos(_:) is obvious - it just applies isFooVisible(_:) as the filter. Which is OK for most implementations, but in some cases, you want to include some optimizations, like:
func filteredFoos(_ foos: [Foo]) -> [Foo] {
if self.dateRange.isInfinite {
return foos
}
// Return the default implementation.
}
I've run into this issue on several occasions and eventually, the only solution to this is to do this:
extension Foo {
func defaultX() -> Int {
return 44
}
func x() -> Int {
return self.defaultX()
}
}
Yes, it's a solution, but IMHO it's not a pretty solution. @Slava_Pestov mentioned in the linked ticket that my original assumption that Foo.f(self)() should work and the ticket is mentioned as in progress. May I ask what exactly is the issue here and if there is an estimate when this might work? Does it depend on something else?
Of course, if anyone has any suggestions how to solve this better, I'm all ears. Thanks.