是否可以将类型约束添加到Swift协议一致性扩展? [英] Is it possible to add type constraints to a Swift protocol conformance extension?

查看:118
本文介绍了是否可以将类型约束添加到Swift协议一致性扩展?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要扩展 Array 来添加一个新协议的符合性 - 但只适用于元素本身符合特定协议的数组。



更一般地说,我希望只有当类型参数匹配某些约束时,才能使用类型参数的类型(不管是协议还是具体类型)实现协议。



从Swift 2.0开始,这看起来不可能。有没有一种方法,我错过了?



示例



假设我们有友好协议:

 协议友好{
func sayHi()
}

我们可以扩展现有类型来实现它:

 扩展字符串:友好{
func sayHi(){
print(来自\(self)!的问候语)
}

$ b $Sally.sayHi()

我们也可以当元素全部为 Friendly 时,扩展 Array 来实现 sayHi()
$ b $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ self {
elem.sayHi()
}
}
}

[Sally,Fred]。sayHi()

此时,类型 [Friendly] 本身应该执行 Friendly ,因为它符合协议 要求。然而,这段代码并不能编译:

 扩展数组:友好的地方Element:Friendly {
func sayHi() {
for elem in self {
elem.sayHi()
}
}
}

错误消息是带有约束的类型'数组'的扩展,不能有一个继承子句,这似乎直接关闭了该门。



是否有间接的解决方法?我可以使用一些聪明的技巧?也许有一种方法涉及到扩展 SequenceType 而不是 Array



  let friendly:Friendly = [Foo,Bar] 


解决方案

7.1)。如错误所示,您不能将协议一致性(继承条款)限制为类型受限的扩展。也许有一天。我不相信这是不可能的,但目前还没有实现。



最接近你可以创建一个包装类型,例如:

  struct FriendlyArray< Element:Friendly> ;: Friendly {
let array:[Element]
init _ array:[Element]){
self.array = array
}
func sayHi(){
为数组中的元素{
elem.sayHi()
}
}
}

让友好:Friendly = FriendlyArray([Foo,Bar])

(您可能希望将 FriendlyArray 扩展为 CollectionType < )

对于我试图做这项工作以及从边缘爬回来的疯狂传说,请参阅< NSData,我的老朋友。


I would like extend Array to add conformance to a new protocol — but only for arrays whose elements themselves conform to a specific protocol.

More generally, I’d like to have types (whether protocols or concrete types) with type parameters implement a protocol only when the type parameters match certain constraints.

As of Swift 2.0, this appears to be impossible. Is there a way I’m missing?

Example

Suppose we have the Friendly protocol:

protocol Friendly {
    func sayHi()
}

We can extend existing types to implement it:

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

"Sally".sayHi()

We can also extend Array to implement sayHi() when its elements are all Friendly:

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

["Sally", "Fred"].sayHi()

At this point, the type [Friendly] should itself implement Friendly, since it meets the protocol’s requirements. However, this code doesn’t compile:

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

The error message is "extension of type 'Array' with constraints cannot have an inheritance clause," which seems to shut the door definitively on that direct approach.

Is there an indirect workaround? Some clever trick I can use? Perhaps there’s a way that involves extending SequenceType instead of Array?

A working solution would make this code compile:

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

解决方案

This is not currently possible in Swift (as of Xcode 7.1). As the error indicates, you can't restrict protocol conformance ("inheritance clause") to a type-constrained extension. Maybe someday. I don't believe there's any deep reason for this to be impossible, but it's currently not implemented.

The closest you can get is to create a wrapper type such as:

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"])

(You would likely want to extend FriendlyArray to be a CollectionType.)

For a tale of my own descent into the madness of trying to make this work, and my crawl back from the edge, see NSData, My Old Friend.

这篇关于是否可以将类型约束添加到Swift协议一致性扩展?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆