Как вставить другой тип элемента в массив - PullRequest
0 голосов
/ 28 января 2019

У меня есть class, который имеет ссылку на другой class.Студенческий класс имеет переменную, которая имеет ссылку на информацию модуля.Я хочу вставить moduleId в массив, но структура состоит из различных типов объектов и имеет тип moduleRef.Я хотел бы получить moduleId, который имеет тип строки.Как получить эту форму элемента moduleId ModuleRef.

class Student {
    var firstName: String
    var lastName: String
    var modulesRefs: [ModuleRef]

    var fullName: String {
        return self.firstName + " " + self.lastName
    }

    init(firstName: String, lastName: String, modulesRefs: [ModuleRef]) {
        self.firstName = firstName
        self.lastName = lastName
        self.modulesRefs = modulesRefs
    }

    func addModuleId(_ moduleId: String) {
        self.modulesRefs.insert(moduleId, at: 0)
    }

     func removeModuleId(_ moduleId: String) {
        self.modulesRefs = self.modulesRefs.filter { $0.moduleId != moduleId }
    }
}

class ModuleRef {
    var moduleName: String
    var moduleId: String
    var moduleStartdate: Int

    init(moduleName: String, moduleId: String, moduleStartdate: Int) {
        self.moduleName = moduleName
        self.moduleId = moduleId
        self.moduleStartdate = moduleStartdate
    }
}

Невозможно преобразовать значение типа 'String' в ожидаемый тип аргумента 'ModuleRef'

Ответы [ 6 ]

0 голосов
/ 28 января 2019

То, что вы пытаетесь сделать, на самом деле означает, что в вашем дизайне есть изъян.

Если вам нужна функциональность для вызова student.addModuleId(moduleId), это означает, что Student не должен содержать массивModuleRef.(Или, по крайней мере, есть механизм для извлечения всего ModuleRef по его идентификатору, а затем вставьте это ModuleRef в массив).

При этом, после выяснения вашего дизайна, к которому он будет:modules: [ModuleRef] или moduleIds: [String], есть еще кое-что, что вы можете использовать из:

Equatable протокола.Если вы заставите ModuleRef соответствовать протоколу Equatable и проверить его равенство с помощью id, то Swift предоставит вам доступ к методу remove(element:_), и вам больше не нужен метод removeModuleId().

Или, если все ModuleId уникальны, вы можете также реализовать протокол Hashable и использовать Set<ModuleRef> вместо массива, чтобы O (1) удалял и вставлял методы.(прямо сейчас, удалить функцию, занимает O (n) время)

0 голосов
/ 28 января 2019

Вы можете вставить значения типа ModuleRef в этот массив.Поэтому я могу изменить функции следующим образом:

func addModuleId(_ moduleId: String) {
        let module = ModuleRef(moduleName: "", moduleId: moduleId, moduleStartdate: 0)
        self.modulesRefs.insert(module, at: 0)
    }

    func removeModuleId(_ moduleId: String) {
        modulesRefs.removeAll(where: { $0.moduleId == moduleId })
    }

Примечание: если вам не нужно moduleName & moduleStartdate все время, вы можете пометить его как необязательный.

0 голосов
/ 28 января 2019

Вы не можете вставить ModuleRef, просто передав String.

Вам необходимо создать экземпляр, например, добавить полное имя учащегося и метку времени UNIX текущей даты

func addModuleId(_ moduleId: String) {
    let moduleRef = ModuleRef(moduleName: self.fullName, 
                              moduleId: moduleId, 
                              moduleStartDate: Int(Date().timeIntervalSince1970))
    self.modulesRefs.insert(moduleRef, at: 0)
}

И удалить объект это более эффективно, однакокласс должен соответствовать Equatable

func removeModuleId(_ moduleId: String) {
    guard let index = self.modulesRefs.firstIndex(where: {$0.moduleId == moduleId}) else { return }
    self.modulesRefs.remove(at: index)
}

Я бы даже объявил moduleStartDate как Date.

0 голосов
/ 28 января 2019

В вашем коде вы сделали class ModuleRef { ... } значения обязательными, и вы просто передаете одно значение moduleId, и вы добавляете его к Array из ModuleRef, что является абсолютно неправильным подходом.Итак, на основании того, что вы сказали здесь, обновленный код вашего кода:

class Student {
    var firstName: String
    var lastName: String
    var modulesRefs: [ModuleRef]

    var fullName: String {
        return self.firstName + " " + self.lastName
    }

    init(firstName: String, lastName: String, modulesRefs: [ModuleRef]) {
        self.firstName = firstName
        self.lastName = lastName
        self.modulesRefs = modulesRefs
    }

    func addModuleId(_ moduleId: String) {
        // This will be your updated intializer where you can pass any value you want and other will be taken as default value
        let moduleRef = ModuleRef(moduleId: moduleId)
        self.modulesRefs.insert(moduleRef, at: 0)
    }

    func removeModuleId(_ moduleId: String) {
        self.modulesRefs = self.modulesRefs.filter { $0.moduleId != moduleId }
    }
}

class ModuleRef {
    var moduleName: String
    var moduleId: String
    var moduleStartdate: Int

    /// Here you can provide all the default values which you don't want to pass
    init(moduleName: String = "", moduleId: String = "", moduleStartdate: Int = 0) {
        self.moduleName = moduleName
        self.moduleId = moduleId
        self.moduleStartdate = moduleStartdate
    }
}

Кроме того, вы также можете передать значение nil для всех составляющих переменную как optional.Дайте мне знать, если у вас есть путаница!

0 голосов
/ 28 января 2019

Вам необходимо изменить тип массива на Любой следующим образом:

var modulesRefs: [Any] 

При доступе к значению из массива,

if let moduleRef = modulesRefs[index] as? ModuleRef {

} else if let str = modulesRefs[index] as? String  {

}
0 голосов
/ 28 января 2019

Вам нужно сделать массив типа Any ..

var modulesRefs: [Any] = []

Вы можете добавить элемент в массив следующим образом ...

modulesRefs.append("Test string")
let obj = ModuleRef(...)
modulesRefs.append(obj)

И когда вы получаете доступ к элементу, вам нужно либо if let, либо guard let, чтобы проверить его тип с безопасностью.

Например,

  for obj in modulesRefs {
    if let strType = obj as? String {
       print("\(obj) is string type")
    } else if let moduleRefObj = obj as? ModuleRef {
       print("\(obj) is ModuleRef type")
  }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...