Swift Array.insert generics

前端 未结 5 1657
盖世英雄少女心
盖世英雄少女心 2020-12-07 03:02
func getIndex(valueToFind: T) -> Int? {...}

mutating func replaceObjectWithObject(obj1: T, obj2: T) {
    if let index =          


        
相关标签:
5条回答
  • 2020-12-07 03:05

    What you are trying to do cannot be done using class/struct functions - @Nate Cook has provided a very good solution using a global function.

    By the way the reason why it doesn't work becomes clearer if in your extension methods you replace T with V: they are different types. That also explains why the same error occurs if you remove the dependency from Equatable: the array holds objects of T type, but you are trying to insert a V value.

    0 讨论(0)
  • 2020-12-07 03:20

    How did you declare your Array extension? The problem is that your generic functions require arguments of type Equatable, but when you declared the array, you specified a specific implementation of an Equatable class, like String. A T is not a String without a cast.

    0 讨论(0)
  • 2020-12-07 03:21

    This is actually not possible via an extension under the existing system of protocols and generics in Swift - you can't add additional constraints to the generic subtype of a type, so you can't extend Array with a method that requires that its contents conform to Equatable.

    You can see this restriction in action with the built-in Array type -- there's no myArray.find(element) method, but there is a global function find() that takes a collection and an element, with a generic constraint that the collection's elements are Equatable:

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

    You can do this for your method - you just need to write a similar top-level function:

    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
    
    0 讨论(0)
  • 2020-12-07 03:24

    You can use extension with a where clause constraint and I'm using 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 
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-07 03:28

    This answer is for a duplicate question stated her: Create swift array extension for typed arrays

    There is a way to solve extensions to Array that are only applicable to a specific type of array. But you have to use an Array with elements of type Any, which sort of circumvents Swift's type system. But the code still works even if there are elements of other types in the array. See example below.

    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]"
    
    0 讨论(0)
提交回复
热议问题