I feel like this may be something too obvious that I just can't see at the moment:
class Wrapper<T> {}
class Foo {
// ❗️ 'Self' is only available in a protocol or as the result of a method in a class; did you mean 'Foo'?
func createWrapper() -> Wrapper<Self> {
return Wrapper<Self>()
}
}
I want this function to be valid for all subclasses of Foo, but how?
You can't do this because inside a class, Self is a shorthand for the runtime type of self, and not just an alternate spelling for the name of the class that lexically contains the definition.
If you could write Self there, it would introduce unsoundness into the typing rules. For example, suppose you have a subclass Bar:
class Bar : Foo {}
Now consider this code:
let bar = Bar()
let result1 = bar.createWrapper()
let foo = (bar as Foo)
let result2 = foo.createWrapper()
The type of result1 is Wrapper<Bar>, but the type of result2 is Wrapper<Foo>. These are two unrelated types.
I would suggest against using this protocol trick. It's actually equivalent to just declaring a class method returning Wrapper<Foo>. The Self in the protocol is a stand-in for the conforming class, not the runtime type of the self value. So using this idiom just obfuscates the intent of the code in my opinion.
It's not equivalent, because you lose the static type of the subclass. I would even say that this trick is becoming a kind of standard practice. For example, here I use it to observe UIControl events, so that the sender is statically not an abstract base class:
button.onEvent(.touchDown).run { (action: (sender: UIButton, event: UIEvent?)) in }