Monday, September 23, 2019

Swift 5.1 Released

Ted Kremenek:

Swift 5.1 builds on the strengths of Swift 5 by extending the stable features of the language to compile time with the introduction of module stability. With module stability it’s now possible to create and share binary frameworks that will work with future releases of Swift. Swift 5.1 also extends the capabilities of the language and the standard library with new features such as property wrappers, opaque result types, key path member lookup, diffing for appropriate collection types, and new APIs for String. Altogether the new features of Swift 5.1 make it easier to design better APIs and reduce the amount of common boilerplate code.

John Sundell:

While that’s still possible, the scope of Self has now been extended to also include concrete types — like enums, structs and classes — enabling us to use Self as a sort of alias referring to a method or property’s enclosing type, like this[…]

Note that this is just syntactic sugar. It’s not like instancetype in Objective-C.

Previously:

Update (2019-09-24): As Joe Groff notes, I misinterpreted Sundell’s comments about Self. It doesn’t refer to the lexically enclosing type, but rather to the dynamic type. So, when used in an expression, it’s like type(of: self):

class Base {
    class func printClass() {
        print("Base")
    }
    
    func selfPrintClass() {
        Self.printClass()
    }
}
class Derived: Base {
    override class func printClass() {
        print("Derived")
    }
}
Derived().selfPrintClass() // prints Derived

This will be useful when calling helper functions from initializers.

His comment that it’s “purely syntactic sugar” only applies to this use of Self. When used to specify the return type, Self is not a mere substitution of the current class name. Instead, it refers to the type of the object (not the type that the method was defined on). So it’s just like instanceof in Objective-C. And you can similarly use it to declare factory methods, in which case Swift will require you to implement them in terms of required initializers:

class Base {
    required init() {} // must be provided unless Base is final

    class func make() -> Self {
        return Self.init()
    }
}
class Derived: Base {}
Base.make() // makes a Base
Derived.make() // makes a Derived

So, Self is really cool, and it can now be used in many more places than before. It’s still not allowed as a parameter type, though. I have a case where I want to ensure that a method has a parameter of the receiver’s own type. I wasn’t able to do this with Self, but I found a workaround using a protocol with an associated type.

1 Comment RSS · Twitter

Self in Swift is exactly like instancetype in Objective-C. What's changed in Swift 5.1 is that you can also use Self to refer to the dynamic type inside method and property bodies, when previously it was only allowed as the return type for methods.

Leave a Comment