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

标签 swift generics

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

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

从 Swift 2.0 开始,这似乎是不可能的。有什么办法是我想念的吗?

示例

假设我们有Friendly协议(protocol):

protocol Friendly {
    func sayHi()
}

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

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

"Sally".sayHi()

我们还可以扩展Array来实现sayHi(),当它的元素都是Friendly时:

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

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

此时,类型[Friendly]本身应该实现Friendly,因为它满足协议(protocol)的要求。 但是,此代码无法编译:

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

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

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

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

let friendly: Friendly = ["Foo", "Bar"]
<小时/>

更新:这已经在 Swift 4.1 中实现,它是一件美丽的事情!

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

最佳答案

编辑:正如更新的问题中所述,自 Swift 4.1 以来现在可以实现这一点

<小时/>

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

您可以获得的最接近的是创建一个包装类型,例如:

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

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

有关我自己陷入疯狂并试图让这项工作成功以及我从边缘爬回来的故事,请参阅 NSData, My Old Friend .

关于swift - 是否可以向 Swift 协议(protocol)一致性扩展添加类型约束?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34861236/

相关文章:

Java泛型?扩展克拉兹

scala - 为什么 scala 编译器说这种类型用在非特化位置?

ios - 禁用文本字段触摸但仍接受编辑?

ios - iOS 10 中的 HLS && .m3u8

swift - 如何解决 requestAccess 中的无限循环(到 :completion:) on EKEventStore?

c# - 为什么 C# 泛型不能像在 C++ 模板中那样从泛型类型参数之一派生?

c# - 具有泛型的约束语法,也从类派生

ios - UITableView 单元格背景颜色在滚动时折叠

swift - 迦太基更新不起作用

swift - 无法推断通用参数 T。工厂方法