Search code examples
swiftpolymorphismprotocolsmetatype

Create class instances from an array of metatypes


Let's suppose I do have a protocol TestProtocol and classes TestClass1 and TestClass2 conforming to TestProtocol:

protocol TestProtocol: AnyObject { }
class TestClass1: TestProtocol { }
class TestClass2: TestProtocol { }

Suppose further that I do have a metatype array defined like

var testArray: [TestProtocol.Type] = [TestClass1.self, TestClass2.self]

How can I create instance objects of TestClass1 and TestClass2 based on the entries of testArray?

p.s.: This should be done without creating a switch construct that checks agains TestClass1.self and TestClass2.self like

var instanceArray: [TestProtocol] = []
for element in testArray {
    if element == TestClass1.self {
        instanceArray.append(TestClass1())
    } else if element == TestClass2.self {
        instanceArray.append(TestClass2())
    }
}

I looked into generics, but did not find a suitable solution, because the metatypes are stored in an array of type [TestProtocol.Type].


Solution

  • This works:

    protocol TestProtocol: AnyObject {
        init()
    }
    
    final class TestClass1: TestProtocol { }
    final class TestClass2: TestProtocol { }
    
    var testArray: [TestProtocol.Type] = [TestClass1.self, TestClass2.self]
    
    for testType in testArray {
        let testInstance = testType.init()
    }
    

    The final classes could be structs as well (but you need to remove the AnyObject constraint)

    Can you let me know if it compiles for you? If not, you need to update your toolchain.