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