This code produces Xcode error messages that lead you in a circle. Let's say I have a protocol called Marker
and I'd like Markers to copy themselves. Here's a first guess...
protocol Marker {
func copy() -> Self
}
class Marker1 : Marker {
func copy() -> Self {
return Marker1() // error here
}
}
(I'm not sure how to use Self
correctly, because I can't find it in the The Swift Programming Language document. If you know where it's documented, please include that in answer.)
That code gives an error on the marked line: Cannot convert return expression of type 'Marker1' to return type 'Self'
and it suggests a fix: Insert ' as! Self'
.
I accept the fix:
...
return Marker1() as! Self
...
This leads to another compiler error: 'Self' is only available in a protocol or as the result of a method in a class; did you mean 'Marker1'?
If I accept that "fix" it goes back to the original error. I'd call that a bug in Xcode. Let's try something else:
func copy() -> Marker1 {
return Marker1()
}
Another error: Method 'copy()' in non-final class 'Marker1' must return `Self` to conform to protocol 'Marker'
Making the class final
does fix the error. But is there a way to do this without making a class final? And where is Self
documented?
With such a hierarchy, you would have to make the class conforming to the protocol final
:
protocol Marker {
func copy() -> Self
}
final class Marker1 : Marker {
func copy() -> Marker1 {
return Marker1()
}
}
The final
is needed because when you don't apply final
and you create a subclass Marker2: Marker1
then copy would not return the correct class Self
any more.
You can workaround that by creating a required
initializer and always create the correct instance:
protocol Marker {
init()
func copy() -> Self
}
class Marker1 : Marker {
required init() {
}
func copy() -> Self {
let copy = type(of: self).init()
return copy
}
}
(original code removed because does not work)
Related: Implementing copy() in Swift
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With