从协议类型实例化类

时间:2015-02-03 20:16:21

标签: swift

我正在编写方法,它采用符合协议的类型并实例化此类的实例。当我构建它时,编译器崩溃了一个段错误。我很欣赏这一点在99%的情况下指向编译器错误,但是我有兴趣看看我尝试做的事情在逻辑上是否正确,或者我只是在编译器中抛出绝对的废话,我不应该'看到它崩溃会感到惊讶。

这是我的代码

protocol CreatableClass {
    init()
}

class ExampleClass : CreatableClass {
    required init() {

    }
}

class ClassCreator {
    class func createClass(classType: CreatableClass.Type) -> CreatableClass {
        return classType()
    }
}

ClassCreator.createClass(ExampleClass.self)

我还试图排除将Type作为方法参数传递为问题的根源,以下代码也会使编译器崩溃:

protocol CreatableClass {
    init()
}

class ExampleClass : CreatableClass {
    required init() {

    }
}


let classType: CreatableClass.Type = CreatableClass.self
let instance = classType()

所以 - 这只是一个简单的编译器错误,我想做的事情看起来是否合理,或者我的实现中有什么东西是错的?

修改

这可以使用下面的@Antonio所示的泛型来实现,但不幸的是我相信对我的应用程序没有用。

用于执行此操作的实际非愚蠢用例类似于

protocol CreatableClass {}
protocol AnotherProtocol: class {}

class ClassCreator {
    let dictionary: [String : CreatableClass]

    func addHandlerForType(type: AnotherProtocol.Type, handler: CreatableClass.Type) {
        let className: String = aMethodThatGetsClassNameAsAString(type)
        dictionary[className] = handler()
    }

    required init() {}
}

1 个答案:

答案 0 :(得分:2)

我通常通过定义泛型方法来做到这一点。试试这个:

class func createClass<T: CreatableClass>(classType: T.Type) -> CreatableClass {
    return classType()
}

<强>更新

一种可能的解决方法是传递一个闭包来创建一个类实例,而不是传递它的类型:

class ClassCreator {
    class func createClass(instantiator: () -> CreatableClass) -> (CreatableClass, CreatableClass.Type) {
        let instance = instantiator()
        let classType = instance.dynamicType

        return (instance, classType)
    }
}

let ret = ClassCreator.createClass { ExampleClass() }

这种情况下的优点是你可以将闭包存储在字典中,并通过知道密钥(与类名称的关系为1:1)按需创建更多实例。

我在几个月前开发的一个微小的依赖注入框架中使用了这个方法,我发现它只适用于@ objc兼容的类,但是它不能满足我的需求......