2014-09-02 55 views
5
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' 
    } 
} 

Tôi có chức năng đó giả sử thay thế một phần tử bằng phần tử khác. Nhưng Im không quen thuộc với Generics và không biết tại sao điều này không hoạt động. Hãy giúp tôi.Swift Array.insert generics

Nếu tôi loại bỏ các Equatable từ đột biến func được thông báo lỗi nhảy vào dòng đầu tiên trong func đó và nếu tôi sau đó thay thế mà với func find() đó mang lại cho tôi những lỗi tương tự như trên dòng 3.

+0

bạn có thể cung cấp việc thực hiện của 'phương pháp insert', hoặc ít nhất là chữ ký của mình? – Antonio

+0

nvm ... Tôi hiểu điều đó - đó là phần mở rộng 'Array', phải không? – Antonio

+0

Hơi tiếp tuyến, nhưng thông báo lỗi đó gây nhầm lẫn vì 'Mảng' sử dụng T làm loại con chung của nó.Nó nói rằng 'T' (kiểu chung cho hàm này) không thể chuyển đổi thành' T' (kiểu chung cho mảng). Nếu bạn thay đổi chữ ký của phương thức để có 'U' thay vì' T', nó sẽ rõ ràng hơn. –

Trả lời

0

thế nào bạn có khai báo số máy lẻ Array của mình không? Vấn đề là các hàm chung của bạn yêu cầu các đối số kiểu Equatable, nhưng khi bạn khai báo mảng, bạn đã chỉ định một triển khai cụ thể của một lớp Equatable, như String. A T không phải là String mà không có dàn diễn viên.

4

này thực sự là không thể qua một phần mở rộng theo hệ thống hiện có của giao thức và Generics trong Swift - bạn không thể thêm những hạn chế bổ sung cho các kiểu phụ chung của một loại, vì vậy bạn không thể mở rộng Array với một phương pháp yêu cầu nội dung của nó tuân theo Equatable.

Bạn có thể thấy hạn chế này trong hành động với built-in loại Mảng - không có phương pháp myArray.find(element), nhưng có một chức năng toàn cầu find() mà có một bộ sưu tập và một phần tử, với một hạn chế chung mà các yếu tố của bộ sưu tập là Equatable:

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

bạn thể làm điều này đối với phương pháp của bạn - bạn chỉ cần phải viết một hàm cấp cao nhất tương tự:

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

Sử dụng loại không khai báo RangeReplaceableCollectionType, 'Generator' không phải là thành viên của loại 'C' – Arbitur

+0

Bạn đang sử dụng loại beta nào? 'RangeReplaceableCollectionType' đến trong phiên bản beta 6. –

+0

Hehe ... Im sử dụng bản beta 4 – Arbitur

0

Những gì bạn đang cố gắng làm không thể được thực hiện bằng cách sử dụng chức năng lớp/struct - @Nate Cook đã cung cấp một giải pháp rất tốt bằng cách sử dụng một chức năng toàn cầu.

Bằng cách lý do tại sao nó không hoạt động trở nên rõ ràng hơn nếu trong các phương pháp mở rộng của bạn, bạn thay thế T với V: chúng là các loại khác nhau. Điều đó cũng giải thích tại sao lỗi tương tự xảy ra nếu bạn loại bỏ sự phụ thuộc từ Equatable: mảng giữ các đối tượng thuộc loại T, nhưng bạn đang cố gắng chèn một giá trị V.

0

Câu trả lời này là cho một câu hỏi trùng lặp tuyên bố cô: Create swift array extension for typed arrays

Có một cách để giải quyết phần mở rộng cho mảng mà chỉ áp dụng đối với một loại hình cụ thể của mảng. Nhưng bạn phải sử dụng một Array với các phần tử thuộc kiểu Any, loại hệ thống kiểu circumvents của Swift. Nhưng mã vẫn hoạt động ngay cả khi có các phần tử của các loại khác trong mảng. Xem ví dụ bên dưới.

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

Bạn có thể sử dụng phần mở rộng với một mệnh đề where khăn và tôi đang sử dụng 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 
     } 
    } 
}