The problem is that security of the strict Swift type means that you cannot mix two instances of the same class with different common parameters. They are effectively regarded as completely different types.
However, in your case, all you do is pass the closure to the Factory instance, which takes the input T and then calls it at any given time using T.init() . Therefore, you can create a closed system to contain type T , which means that you do not need your general parameter to cover your class. Instead, you can limit it only to the scope of the initializer.
You can do this by specifying resultHandler as a closure of Void->Void and creating it, wrapping the passed closure in the initializer with another closure - and then passing T.init() to the provided closure (providing a new instance is created with every call).
Now, when you call your resultHandler , it will create a new instance of the type that you define in the closure you pass, and pass that instance to the closure.
This does not violate security rules such as Swift, since the result of T.init() is still known due to the explicit input of the closure that you pass. This new instance is then passed to your closure, which has an appropriate input type. Also, since you never pass the result of T.init() to the outside world, you never have to set the type in the definition of the Factory class.
Since your Factory class no longer has a common parameter, you can freely mix different instances.
For instance:
class Factory { let resultHandler: () -> () init<T:Defaultable>(resultHandler: (T) -> ()) { self.resultHandler = { resultHandler(T.init()) } } func callResultHandler() { resultHandler() } } // Create Int factory variant... let integerFactory = Factory(resultHandler: { (i: Int) in debugPrint(i) }) // Create String factory variant... let stringFactory = Factory(resultHandler: { (i: String) in debugPrint(i) }) // Create a queue of factories of some unknown generic type... var factoryQueue = [Factory]() // Add factories to the queue... factoryQueue.append(integerFactory) factoryQueue.append(stringFactory) // Call the handler for each factory... for factory in factoryQueue { factory.callResultHandler() } // prints: // 0 // ""
To adapt this to input NSData , you can simply change the closing function resultHandler and callResultHandler() to input NSData . Then you just need to change the wrapped closure in your initializer to use the init(data:) throws initializer, and convert the result to optional or do your own error handling to handle what it might throw.
For instance:
class Factory { let resultHandler: (NSData) -> () init<T:Defaultable>(resultHandler: (T?) -> ()) { self.resultHandler = {data in resultHandler(try? T.init(data:data))