当使用带闭包的泛型函数时,Swift会创建错误类型的实例

时间:2015-04-24 02:56:59

标签: swift generics closures

我试图创建一个以闭包为参数的泛型函数。我有问题,所以为了解决问题,我创建了以下可在游乐场中运行的代码。

    <form:form action="" modelAttribute="newSchoolContractForm" enctype="multipart/form-data" id="newSchoolContractForm">
    <table>
    <tr>
    <td><label for="">Date : </label></td>
    <td><form:input path="startDate" id="startDate" title="StartDate" />   </td>
    </tr>
    <tr>
    <td><label for="">Attachment</label></td>
    <td><input type="file" name="file" id="file"/></td>
    </tr>
    </table>
    </form>

此代码生成以下输出:

class BaseClass {
    init(message: String) {
        println("Base class says: " + message)
    }

    func getMyName() -> String {
        return "BaseClass"
    }
}

class SubClass: BaseClass {
    override init(message: String) {
        println("Subclass says: " + message)
        super.init(message: message)
    }

    override func getMyName() -> String {
        return "SubClass"
    }

    func specialAbility() {
        println("only I can do this!")
    }
}

func makeInstance<T: BaseClass>(callback: (T -> Void)?) {
    callback?(T(message: "hello"))
}

makeInstance() {
    (instance: SubClass) in
    println("makeInstance1 built a " + instance.getMyName())
    println("I think it is a \(_stdlib_getDemangledTypeName(instance))")

    //instance.specialAbility() - uncommenting this throws EXC_BAD_ACCESS at runtime
}

makeInstance() {
    (instance: BaseClass) in
    println("makeInstance2 built a " + instance.getMyName())
    println("I think it is a \(_stdlib_getDemangledTypeName(instance))")
}

Swift不允许您在函数调用中明确指定类型(例如makeInstance),因此我希望编译器根据调用中的闭包类型推断它。它似乎每次都创建一个BaseClass实例。未调用SubClass初始值设定项,其成员似乎是BaseClass的成员。

我敢说这似乎是斯威夫特的一个错误;如果您尝试在第一个闭包中访问SubClass的成员,编译器没有问题,但在运行时,会抛出异常(请参阅我在代码中的注释)。

我有什么想法可以解决这个问题吗?如果不清楚,我想在闭包期望的时候创建一个BaseClass的子类。

1 个答案:

答案 0 :(得分:2)

我实际上只是将初始化程序更改为如下所示:

class BaseClass {
    required init(message: String) {
        println("Base class says: " + message)
    }

    func getMyName() -> String {
        return "BaseClass"
    }
}

class SubClass: BaseClass {
    required init(message: String) {
        println("Subclass says: " + message)
        super.init(message: message)
    }
    ...
 }

它没有任何问题