Self' is only available in a protocol or as the result of a class method
The problem, I suspect, is that Self is ambiguous; it means "this class or a subclass, whatever the thing happens to be at the time we are called". In other words, Self is polymorphic. But you can't make an array consisting of two different classes, for example. And although the class may permit a certain initializer, we cannot know in advance that its subclass will.
The solution is to use the class name itself. Here's an example for a struct Thing:
extension Thing {
static func makeTwo() -> (Thing, Thing) {
return (Thing(), Thing())
}
}
How to use Self for method return types in Swift?
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
Why using Self as return type is not considered as the protocol's constraint?
Because it's not useful to have a Self
as a parameter type of a method. Suppose that you can do:
protocol P {
func f(_ x: Self)
}
class A: P {
func f(_ x: Self) {
// not relevant
}
}
class B: A { }
Now suppose I have:
func g(x: A) {
// what can I do with x?
}
The fact is, there is no way to call x.f
. Because I can pass an instance of B
to x
, in which case x.f
would accept a B
instead. x
could be an instance of any subclass of A
that I have no way of knowing at compile time, so I don't know what I can pass to x.f
.
Compare that to Self
used as the return type:
protocol P {
func f() -> Self
}
// Implementation:
class A: P {
func f() -> Self {
self
}
}
class B: A { }
func g(x: A) {
let foo: A = x.f()
}
Here, we know that I can at least assign the return value of x.f
to a variable of type A
. Even if x
is an instance of B
, which means that f
returns a B
, we can still assign that to a variable of type A
.
Swift, Self from AnyObject
You can simply return User?
from your class function, if this is an option:
public class func returnFirstSelf() -> User? {
if let found = findByID("1") as? User {
return found
}
return nil
}
There's currently no way (I'm aware of) to return Self?
with Swift as it stands. The problem is that Self
has a somewhat... "dynamic" meaning, separate from concrete types, protocols, and even generics. A particular example that demonstrates this is: What if you have a class StudentUser
that extends User
? If you tried to implement it like this:
class func returnFirstSelf() -> Self? {
if let found = findById("1") as? Self { // Note the check that 'found' is a 'Self'
return found
}
return nil
}
Then you encounter a compiler error because you cannot use Self
outside the result of a protocol or class method. And if you try to implement it like this:
class func returnFirstSelf() -> Self? {
if let found = findById("1") as? User { // Note 'User' instead of 'Self'
return found
}
return nil
}
Then you run the risk of Self
actually meaning StudentUser
, and even if you pass the check that requires found
to be a User
, it doesn't guarantee that found
will be a StudentUser
. This will occur in the case that StudentUser
does not override the method to ensure that the as?
checks against StudentUser
.
The critical flaw here in my opinion is that you cannot use the required
keyword on class methods, requiring subclasses to override them. This would allow the compiler to ensure that any subclasses have overridden the method and provided an implementation that can guarantee type safety.
Method in non-final class must return `Self` to conform to protocol
In Swift 3 or 4:
import Foundation
protocol P {
static func f() -> Self
static func g() -> Self
}
extension P {
static func f() -> Self {
return g()
}
}
extension Data: P {
static func g() -> Data {
return self.init()
}
}
Or you can replace your class with a final subclass:
import Foundation
protocol P {
static func f() -> Self
static func g() -> Self
}
extension P {
static func f() -> Self {
return g()
}
}
import Foundation
final class MyData: NSData {}
extension MyData: P {
static func g() -> Self {
return self.init()
}
}
If NSData is one of those class clusters that can't easily be subclassed (you'll see a stacktrace with __CFRequireConcreteImplementation
), you may have to create a final class wrapper for a real NSData instead of using a subclass.
Related Topics
Testing If a Decimal Is a Whole Number in Swift
Swift Nsusernotification Doesn't Show While App Is Active
Swift: Google Maps Draw Waypoint Polyline
Swift:Difference in '!' and '' in Swift
Sort Dictionary Keys by Value, Then by Key
Disable Https Get Certificate Check in Swift 5
Parse.Com Pfgeopoint.Geopointforcurrentlocationinbackground Not Doing Anything
Swift Package Manager Unable to Compile Ncurses Installed Through Homebrew
How to Add Documentation to Enum Associated Values in Swift
No Designated Init for Skshapenode(Circleofradius: Radius)
Swiftui Behavior of .Frame(Height: Nil)
How to Handle Menu Button Action in Tvos Remote
What's the Rationale of Swift's Size Methods Taking 'Int'S
Swift: Oslog/Os_Log Not Showing Up in Console App
Swift 3 Warning: Non-Optional Expression of Type 'String' Used in a Check for Optionals
I Have Trouble Using Cornerradius and Borders on a Textfield in Swiftui