"通用参数' T'无法推断" Swift

时间:2018-05-09 03:16:32

标签: swift

我正在尝试使用通用"来练习#34;我遇到了2个错误:

  

通用参数' T'无法推断   参考泛型类型' GenericObject'需要< ...>

中的参数

GenericManager级中的2个错误。请参考以下代码。我该如何解决这个问题?

class User {
    var name: String
    init(name: String) {
        self.name = name
    }
}

class Employee {
    var name: String
    var position: String
    init(name: String, position: String) {
        self.name = name
        self.position = position
    }
}

class GenericObject<T> {
    var items = [T]()
    init(forType: T.Type) {}

    func addObject(_ obj: T) {
        self.items.append(obj)
    }
}

class GenericManager {
    //issue: Generic parameter 'T' could not be inferred
    var objects = [GenericObject]()        

    //issue: Reference to generic type 'GenericObject' requires arguments in <...>
    func addObject(_ obj: GenericObject) {
        self.objects.append(obj)
    }
}

let u = User(name: "User")
let uo = GenericObject(forType: User.self)
uo.addObject(u)


let e = Employee(name: "Employee", position: "session manager")
let eo = GenericObject(forType: Employee.self)
eo.addObject(e)

let manager = GenericManager()
manager.addObject(uo)
manager.addObject(eo)

2 个答案:

答案 0 :(得分:2)

编译器需要知道T的类型,在这种情况下,您还没有提供它。

你可以这样做:

var objects = [GenericObject<YourTypeHere>]()

例如,如果GenericObject将包含Int数组,则它将如下所示:

var objects = [GenericObject<Int>]()

我注意到您更新了问题。知道你想要实现的目标会很有帮助,但无论如何我都会尽力帮助你。

当你有一个通用对象时,你需要在编译时告诉编译器通用的类型,这就是为什么它抱怨不能推断出类型,它需要知道。

由于您希望能够将对象添加到GenericManager数组,因此您需要在这两种情况下使用通用,因此您可以像这样修改您的类:

class GenericManager<T> {
    var objects = [GenericObject<T>]()

    func addObject(_ obj: GenericObject<T>) {
        self.objects.append(obj)
    }
}

但是,由于对象必须具有相同的通用,因此您无法将GenericObject<User>GenericObject<Employee>添加到同一个经理,您可以做的是将其实现为{ {1}},并对GenericObject<Any>执行相同操作,然后它将如下所示:

GenericManager

请记住,这将失去通用设备可以做的任何优势,你可以做的是创建一个协议或公共超类,而不是let u = User(name: "User") let uo = GenericObject(forType: Any.self) uo.addObject(u) let e = Employee(name: "Employee", position: "session manager") let eo = GenericObject(forType: Any.self) eo.addObject(e) let manager = GenericManager<Any>() manager.addObject(uo) manager.addObject(eo) 使用它,但这取决于你&#39;重新尝试实现。

如果您有任何其他问题,请添加评论,而不是默默地更新您的问题。

答案 1 :(得分:0)

您遇到的问题是您正在尝试使用泛型,但希望在GenericManager中忽略它并存储对不同类型对象的引用。

考虑一下 - 当你致电manager.objects[0]时,你期望什么回来?

你可以使用Any进行类型擦除来解决这个问题,正如EmilioPelaez建议的那样。然而,这通常是一种代码,会导致整个代码中出现乱码。

一种替代方法是使用enum指定您想要表示的不同类型的数据:

enum GenericObject {
    case users([User])
    case employees([Employee])
}
...
let uo = GenericObject.users([ u ])
...
let eo = GenericObject.employees([ e ])

现在,当您访问GenericManager内的属性时,您需要切换不同的受支持类型,当您添加新类型时,只要您使用GenericObject,就需要实现代码