Search code examples
swiftgenericsstructswift-extensionsswift-protocols

Swift: Generic Protocols


I have some swift structs for which protocol compliance is generated with individual extensions with equal methods names which just differ in their return types which are struct dependent. On top of That I want to use them in a generic function which Calls a protocol conforming function for a generic type). I tried to accomplish this like that: //: Playground - noun: a place where people can play

import UIKit

protocol FooProt {
typealias T;
static func createMe<T>()->T;
}


struct FooStruct{

}


extension FooStruct: FooProt{
typealias T = FooStruct;
static func createMe  () -> FooStruct{
    return  FooStruct();
}

}


class Creator{
fun  createOne<T where T:FooProt>(type:T.Type){
   let instance  =  T.createMe();
} 

}

Unfortunately I get the following error : /var/folders/sn/78_zvfd15d74dzn01mdv258h0000gq/T/./lldb/3741/playground6.swift:7 :17: note: protocol requires function 'createMe()' with type ' () -> T' (aka '<τ_1_0> () -> τ_1_0') static func createMe()->T;

What exactly doesn't comply here and is there a workaround ?


Solution

  • There are several problems with your code. On the one hand you have defined a protocol with an associated type. However, you define your createMe() method as a generic which uses some other type. I don't think that was your intent. I think your intent was to have a createMe() method that returns the same type as the protocol's associated type. In this case you need to remove the from the createMe() method. Also, the name createMe() implies that you aren't just returning any type, but the type of the object on which this method is being called. In this case, you don't even need an associated type protocol. You just need a protocol with a Self constraint which allows your code to be a bit simpler. In your Creator's createOne method, your type constraint is more complex than needed.

    I think you want the following code:

    protocol FooProt {
        static func createMe()->Self;
    }
    
    
    struct FooStruct{
    }
    
    
    extension FooStruct: FooProt {
        static func createMe() -> FooStruct {
            return FooStruct();
        }
    }
    
    
    class Creator{
        func createOne<T:FooProt>(type: T.Type) -> T {
            return T.createMe()
        }
    }
    
    
    let foo = Creator().createOne(FooStruct.self)