Consider I have this abstract base class with one virtual method with a return type of Foo
:
class Foo {
func foo() -> Foo { fatalError("abstract") }
}
Because Foo
is in covariant position, a subclass can return an instance of a subclass of Foo
, like this:
final class SubFoo: Foo {
let value: Int = 0
override func foo() -> SubFoo {
return SubFoo()
}
}
This is convenient because when a given instance is statically known to be of type SubFoo
, then .foo()
will return an instance of type SubFoo
. At the opposite, when an instance of a subclass of Foo
is erased to Foo
, then .foo()
returns a type-erases Foo
:
let subFoo = SubFoo().foo() // Statically known to be of type `SubFoo`
let foo = (SubFoo() as Foo).foo() // `foo` is erased to `Foo`
My issue is that I cannot find a way to replicate this nice behavior with protocols and existentials:
protocol Bar {
func bar() -> any Bar
}
struct ImplBar: Bar {
var value: Int = 0
func bar() -> ImplBar { // Error: returning `ImplBar` not allowed
return ImplBar()
}
}
Is there a way to make the protocol version to work or this behavior is not supported by Swift protocols/existentials?