Swift Array.insert泛型

时间:2014-09-02 19:02:01

标签: arrays generics swift

func getIndex<T: Equatable>(valueToFind: T) -> Int? {...}

mutating func replaceObjectWithObject<T: Equatable>(obj1: T, obj2: T) {
    if let index = self.getIndex(obj1) {
        self.removeAtIndex(index)
        self.insert(obj2, atIndex: index)           // Error here: 'T' is not convertible to 'T'
    }
}

我有这个函数,假设用另一个元素替换元素。但我对Generics不太熟悉,也不知道为什么这不起作用。请帮忙。

如果我从变异函数中删除Equatable,则错误消息会跳转到该func中的第一行,如果我然后将其替换为func find(),它会给出与第3行相同的错误。

5 个答案:

答案 0 :(得分:4)

在Swift中现有的协议和泛型系统下,通过扩展实际上是不可能的 - 您无法在类型的通用子类型中添加其他约束,因此您可以&# 39; t使用要求其内容符合Array的方法扩展Equatable

您可以使用内置数组类型查看此限制 - 没有myArray.find(element)方法,但全局函数find()采用集合和元素,使用通用约束,集合的元素为Equatable

func find<C : CollectionType where C.Generator.Element : Equatable>(domain: C, value: C.Generator.Element) -> C.Index?

可以为您的方法执行此操作 - 您只需要编写类似的顶级函数:

func replaceObjectWithObject<C : RangeReplaceableCollectionType where C.Generator.Element : Equatable>(inout collection: C, obj1: C.Generator.Element, obj2: C.Generator.Element) {
    if let index = find(collection, obj1) {
        removeAtIndex(&collection, index)
        insert(&collection, obj2, atIndex: index)
    }
}

var myArray = [1, 2, 3, 4, 5]
replaceObjectWithObject(&myArray, 2, 7)
// 1, 2, 7, 4, 5

答案 1 :(得分:0)

您是如何申报Array分机的?问题是您的泛型函数需要Equatable类型的参数,但是当您声明数组时,您指定了Equatable类的特定实现,如StringT不是没有演员的String

答案 2 :(得分:0)

使用类/结构函数无法完成您的工作 - @Nate Cook使用全局函数提供了一个非常好的解决方案。

顺便说一下,如果在您的扩展方法中将T替换为V,那么它不起作用的原因会变得更清晰:它们是不同的类型。这也解释了为什么从Equatable中删除依赖项时会发生相同的错误:数组包含T类型的对象,但您尝试插入V值。

答案 3 :(得分:0)

这个答案是针对一个重复的问题,她说:Create swift array extension for typed arrays

有一种方法可以解决仅适用于特定类型数组的Array扩展。但是你必须使用一个具有Any类型元素的Array,这种类型绕过了Swift的类型系统。但即使数组中有其他类型的元素,代码仍然有效。见下面的例子。

class Job {
    var name: String
    var id: Int
    var completed: Bool

    init(name: String, id: Int, completed: Bool) {
        self.name = name
        self.id = id
        self.completed = completed
    }
}

var jobs: [Any] = [
    Job(name: "Carpenter", id: 32, completed: true),
    Job(name: "Engineer", id: 123, completed: false),
    Job(name: "Pilot", id: 332, completed: true)]



extension Array {

    // These methods are intended for arrays that contain instances of Job

    func withId(id: Int) -> Job? {
        for j in self {
            if  (j as? Job)?.id == id {
                return j as? Job
            }
        }
        return nil
    }

    func thatAreCompleted() -> [Job] {
        let completedJobs =  self.filter { ($0 as? Job) != nil && ($0 as? Job)!.completed}
        return completedJobs.map { $0 as! Job }
    }
}

jobs.withId(332)
println(jobs.withId(332)?.name)
//prints "Optional("Pilot")"

let completedJobs = jobs.thatAreCompleted().map {$0.name}
println(completedJobs)
//prints "[Carpenter, Pilot]"

答案 4 :(得分:0)

您可以使用带有where子句约束的扩展名,并且我使用Xcode 7.3.1

extension Array where Element: Equatable {
    func testEqutability() {
        let e1 = self[0]
        let e2 = self[1]
        if e1 == e2 {//now we can use == to test Element equtability
            //do something 
        }
    }
}