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行相同的错误。
答案 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
类的特定实现,如String
。 T
不是没有演员的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
}
}
}