Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pure Swift class conforming to protocol with static method - issue with upcasting

Given we have a Swift protocol with one static method:

protocol Creatable: class {
    static func create() -> AnyObject
}

and a pure Swift class which conforms to the protocol:

class Foo : Creatable {
    static func create() -> AnyObject {
        return Foo() as AnyObject
    }
}

Later on when one tries to make use of that protocol by operating on type Creatable e.g.:

var f : Creatable = Foo.self
f.create()

The compiler complains with the following:

error: type 'Foo.Type' does not conform to protocol 'Creatable'

The question is: is this a Swift limitation or I'm using the protocols and static/class method in the wrong way.

Objective-C equivalent would be something like:

Class someClass = [Foo class];
if ([someClass conformsToProtocol:@protocol(Creatable)]) {
    [(Class <Foo>)someClass create];
}
like image 397
Aleksander Zubala Avatar asked Mar 10 '15 20:03

Aleksander Zubala


2 Answers

A Creatable reference points to an instance of Foo, not to the Foo type itself.

To get the equivalent of the class-level protocol implementation, you need an instance of Creatable.Type:

let c: Creatable.Type = Foo.self

However, you’ll get an error when you then try to use it:

// error: accessing members of protocol type value 'Creatable.Type' is unimplemented
c.create()

All that said, is there a reason why you can’t just use functions to fulfill your requirement, instead of metatypes?

let f = Foo.create
// f is now a function, ()->AnyObject, that creates Foos
let someFoo = f()
like image 189
Airspeed Velocity Avatar answered Sep 23 '22 11:09

Airspeed Velocity


Using .Type is the key:

var f : Creatable.Type = Foo.self

And this no longer gives the "unimplemented" error. See full code below:

protocol Creatable: class {
    static func create() -> AnyObject
}

class Foo : Creatable {
    static func create() -> AnyObject {
        return Foo() as AnyObject
    }
}

var f : Creatable.Type = Foo.self
f.create()
like image 22
Jerry Avatar answered Sep 24 '22 11:09

Jerry