Zomagk Zomagk - 9 days ago 7
Swift Question

Is it possible for protocols to have a default implementation of static factory methods?

Consider a protocol that have a factory method:

public protocol Frobnicator {

func frobnicate()

static func makeRightFrobnicator() -> Frobnicator
}

private class SomeFrobnicatorImplementation: Frobnicator { ... }
private class AnotherFrobnicatorImplementation: Frobnicator { ... }

public extension Frobnicator {

static func makeRightFrobnicator() -> Frobnicator {
if something {
return SomeFrobnicatorImplementation()
} else {
return AnotherFrobnicatorImplementation()
}
}
}


I want to be able to construct different implementors at different times. The implementors themselves are private to the module, whereas the protocol is public to use in the client code.

When I try the code similar to that above, I get “Static member
makeRightFrobnicator
cannot be used on protocol metatype
Frobnicator.Protocol
.”

Is there any way around it, or should I just use a free function?

Answer

The static function implementation is legal:

protocol P {
    static func f() -> P
    init()
}

extension P {
    static func f() -> P {return self.init()}
}

But you'll notice that in order to get it to compile, I had to guarantee to the compiler that I have in hand a legal way to make a P so as to able to return one.

The issue in your code is the attempt to return a specific adopter of your protocol, like a SomeFrobnicatorImplementation. A protocol is agnostic as to who adopts it. To put it another way, you cannot guarantee within the protocol definition that SomeFrobnicatorImplementation will in fact be an adopter of this protocol. Thus, that part of your code is illegal.