Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
是否可以向Swift协议一致性扩展添加类型约束?_Swift_Generics - Fatal编程技术网

是否可以向Swift协议一致性扩展添加类型约束?

是否可以向Swift协议一致性扩展添加类型约束?,swift,generics,Swift,Generics,我想扩展Array以添加对新协议的一致性,但仅限于元素本身符合特定协议的数组 更一般地说,我希望具有类型参数的类型(无论是协议还是具体类型)只在类型参数匹配某些约束时实现协议 从Swift 2.0开始,这似乎是不可能的。有没有我错过的路 例子 假设我们有友好的协议: protocol Friendly { func sayHi() } 我们可以扩展现有类型来实现它: extension String: Friendly { func sayHi() { prin

我想扩展
Array
以添加对新协议的一致性,但仅限于元素本身符合特定协议的数组

更一般地说,我希望具有类型参数的类型(无论是协议还是具体类型)只在类型参数匹配某些约束时实现协议

从Swift 2.0开始,这似乎是不可能的。有没有我错过的路

例子 假设我们有友好的协议:

protocol Friendly {
    func sayHi()
}
我们可以扩展现有类型来实现它:

extension String: Friendly {
    func sayHi() {
        print("Greetings from \(self)!")
    }
}

"Sally".sayHi()
我们还可以扩展
数组
来实现
sayHi()
,当它的元素都是友好的
时:

extension Array where Element: Friendly {
    func sayHi() {
        for elem in self {
            elem.sayHi()
        }
    }
}

["Sally", "Fred"].sayHi()
此时,类型
[Friendly]
本身应该实现
Friendly
,因为它满足协议的要求。但是,此代码不编译:

错误消息是“带有约束的'Array'类型的扩展不能有继承子句”,这似乎最终关闭了直接方法的大门

有间接的解决办法吗?我能用些聪明的把戏吗?也许有一种方法需要扩展
SequenceType
而不是
Array

一个可行的解决方案将使此代码得以编译:

let friendly: Friendly = ["Foo", "Bar"]

更新:这已经登陆Swift 4.1,这是一件美妙的事情


扩展数组:Friendly where元素:Friendly
示例现在按照原始问题中给出的方式进行编译。

编辑:如更新问题中所述,自Swift 4.1以来,现在可以进行编译


这在Swift中目前是不可能的(从Xcode 7.1开始)。如错误所示,您不能将协议一致性(“继承子句”)限制为受类型约束的扩展。也许有一天。我不相信有任何深层次的原因使这不可能,但它目前尚未实施

最接近的方法是创建包装器类型,例如:

struct FriendlyArray<Element: Friendly>: Friendly {
    let array: [Element]
    init(_ array: [Element]) {
        self.array = array
    }
    func sayHi() {
        for elem in array {
            elem.sayHi()
        }
    }
}

let friendly: Friendly = FriendlyArray(["Foo", "Bar"])
struct Friendly数组:友好{
let数组:[元素]
init(u数组:[元素]){
self.array=array
}
func sayHi(){
数组中的元素{
elem.sayHi()
}
}
}
让友好:友好=友好阵列([“Foo”,“Bar”])
(您可能希望将
FriendlyArray
扩展为
CollectionType


有关我自己陷入疯狂尝试实现这一目标的故事,以及我从边缘爬回来的故事,请参见。

好消息是,您所要求的
条件一致性将在Swift 4.1中实现:


对于Swift泛型出现故障的许多情况,struct包装器似乎是一种解决方案。例如,见证API方法返回
AnySequence
,因为它们无法返回
SequenceType
…可能在未来的swift版本中:我相信这会到来。它没有进入Swift 4,但似乎正在积极开发中。(参见上一条评论的链接)这似乎是Swift 3.0的愿望列表,比较:“……使受约束的扩展符合新协议的能力(即,一个可均衡元素数组是可均衡的)…”
struct FriendlyArray<Element: Friendly>: Friendly {
    let array: [Element]
    init(_ array: [Element]) {
        self.array = array
    }
    func sayHi() {
        for elem in array {
            elem.sayHi()
        }
    }
}

let friendly: Friendly = FriendlyArray(["Foo", "Bar"])