Swift泛型参数不能绑定到非@objc协议

时间:2015-05-04 16:27:43

标签: swift generics

以下代码产生编译错误“通用参数”T“无法绑定到失败行上的非@objc协议类型'AAA'。当我使用类而不是协议时,它可以正常工作。 ,如果我将@objc添加到协议中它也可以,但只能在6.4 beta。任何建议都会有所帮助。

protocol AAA {
    var id: String { get set }
}

class BBB: AAA {
    var id: String = ""
}

class BBBService {
    func getAll<T:AAA>() -> [T] {
        var returnArray:[T] = [T]()

        return returnArray
    }
}

class TestIt
{
    func myTest() {
        var service = BBBService()
        var fail:[AAA] = service.getAll() // fails with Generic parameter "T" cannot be bound to non-@objc protocol type AAA
        var succeed:[BBB] = service.getAll()
    }
}

这也失败了:

<T where T:AAA>

更新 - 从实际角度来看,添加@objc会导致我的应用中出现其他问题。所以,在这个时间点,这不是一个选择。

1 个答案:

答案 0 :(得分:0)

麻烦在于这一行:

 getAll<T: AAA>() -> [T]

您声明T必须是实现协议AAA的具体类型。区分协议AAA很重要,即代码如下:

func getAll() -> [AAA] {
    var returnArray: [AAA] = [BBB()]

    return returnArray
}

工作正常(返回对AAA的引用数组 - 符合对象,可以是BBB类型,或类型CCC),并且:

func getAll<T: AAA>() -> [T] {
    var returnArray: [T] = [] // what is T?  No idea.

    return returnArray
}

您要对编译器说“给我写一个getAll版本,其中T可以替换为实现AAA的任何特定类型。”

这就是您的第二个版本编译的原因 - 您将T修改为实际类型BBB

请记住,T可能是一个结构。在这种情况下,返回的数组必须专门针对所持有的任何结构进行大小调整,并将其作为数组中的值。相反,如果协议是@objc,在这种情况下,至少只知道它是固定大小的类引用。

如果您真正想要的是一组协议,则应删除通用占位符并返回一组协议:

func getAll() -> [AAA] {
    var returnArray: [AAA] = []

    return returnArray
}