Can't extend a class to conform to ExpressibleByStringLiteral


(Jens Alfke) #1

I’m making extensive use of NSPredicates, which can be initialized from format strings, so I decided to extend the class to implement ExpressibleByStringLiteral. I adapted an example in the book Advanced Swift to get this:

extension NSPredicate : ExpressibleByStringLiteral {
    public convenience init(stringLiteral value: String) {
        self.init(format: value, argumentArray: nil)
    }
    public convenience init(extendedGraphemeClusterLiteral value: String) {
        self.init(format: value, argumentArray: nil)
    }
    public convenience init(unicodeScalarLiteral value: String) {
        self.init(format: value, argumentArray: nil)
    }
}

Unfortunately this doesn’t compile (in Swift 3.0.2 / Xcode 8.2.1):

error: initializer requirement 'init(stringLiteral:)' can only be satisfied by a `required` initializer in the definition of non-final class 'NSPredicate'
    public convenience init(stringLiteral value: String) {
                       ^
As far as I can tell, what’s going on here is: because ExpressibleByStringLiteral doesn’t define its initializers as `convenience`, they’re required by default; thus any implementation of them has to be required; but a required initializer can only appear in the class definition not an extension.

So does this mean that it’s impossible to add conformance to ExpressibleByStringLiteral in a class extension?

—Jens