Ошибка «Общий параметр« T »не может быть выведена» в Swift - PullRequest
0 голосов
/ 09 мая 2018

Я пытаюсь практиковать "класс с дженериком". Я столкнулся с 2 ошибками:

Общий параметр 'T' не может быть выведен
Ссылка на универсальный тип 'GenericObject' требует аргументов в <...>

2 ошибки в классе GenericManager. Пожалуйста, используйте следующий код Как мне решить эту проблему?

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 голосов
/ 09 мая 2018

Проблема, с которой вы столкнулись, заключается в том, что вы пытаетесь использовать обобщенные элементы, но хотите игнорировать это в GenericManager и сохраняете ссылки на объекты различных типов.

Обдумайте это - когда вы позвоните manager.objects[0], что вы ожидаете получить?

Вы можете решить эту проблему с помощью стирания типа, используя Any, как предложил ЭмилиоПелез.Однако это часто кодовый код, который приводит к взлому в вашем коде.

В качестве альтернативы можно использовать enum для указания различных типов данных, которые вы хотите представить:

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

Теперь, когда вы получите доступ к свойствам внутри GenericManager, вы будететребуется переключаться между различными поддерживаемыми типами, и когда вы добавляете новый тип, вам потребуется реализовывать код всякий раз, когда вы используете GenericObject

0 голосов
/ 09 мая 2018

Компилятору необходимо знать тип 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> к одному и тому же менеджеру, что вы можете сделать, это реализовать их как 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)

Имейте в виду, что это лишит вас любого преимущества, которое могли бы дать дженерики, что вы могли бы сделать - создать протокол или общий суперкласси используйте его вместо Any, но это зависит от того, чего вы пытаетесь достичь.

Если у вас есть какие-либо дополнительные вопросы, пожалуйста, добавьте комментарий вместо того, чтобы молча обновлять ваш вопрос.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...