如何扩展满足多个约束条件的协议 - Swift 2.0

40

我正在尝试提供协议的默认实现,以满足其他协议的多个约束条件。

给定以下协议:

public protocol Creature {
    var name: String { get }
    var canMove: Bool { get }
}

public protocol Animal: Creature {}

public protocol Moveable {
    var movingSpeed: Double { get set }
}

public protocol Agend {
    var aged: Int { get }
}

我可以使用一个条件语句对 Self 进行扩展:

// all animals can move
extension Moveable where Self: Animal {
    public var canMove: Bool { return true }
}

但是,如果我想为符合 AnimalAged 协议的类型提供默认的 Moveable 实现,该如何设置约束条件呢?类似下面这样的方式?还是在 where 子句中有一些 "添加" 或 "或" 选项?

// Pseudocode which doesn't work
extension Moveable where Self: Animal && Self: Aged {
    public var canMove: Bool { return true }
}

顺便说一下,如果想查看我编写的最终代码示例,请访问:http://audreyli.me/2015/06/29/strategy-design-pattern-updated-using-protocol-extension-in-swift-2-0/ - Audrey Li
4个回答

75

你可以使用一个协议组合

extension Moveable where Self: protocol<Animal, Aged> {
    // ... 
}

或者只需要一个接一个地添加符合性:

extension Moveable where Self: Animal, Self: Aged {
    // ... 
}

5
当需要符合两者时,这很好,但如果您想要检查符合其中一个怎么办?类似于:extension Movable where Self: protocol<Animal || Aged>... - Dylan
1
@Dylan,这个语法用于表示一个类型符合某个协议,而不是检查符合性。要检查是否符合协议,请参考AirspeedVelocity在这里的答案https://dev59.com/p14c5IYBdhLWcg3wQoY5 - ABakerSmith
显然有一个新的语法,协议<..>已被移除。在Swift 4中使用&语法。 - Glenn Howes

42

截至本帖发布时,答案使用的是protocol<Animal, Aged>

在Swift 3.0中,protocol<Animal, Aged>被弃用了。

在Swift 3.0中,正确的用法是:

extension Moveable where Self: Animal & Aged {
    // ... 
}

您还可以将协议组合使用 typealias。当您在多个位置使用协议组合时,这非常有用(可以避免重复并提高可维护性)。

typealias AgedAnimal = Aged & Animal
extension Moveable where Self: AgedAnimal {
    // ... 
}

1
我知道时间过去了一些,但是typealias类型在Objective-C中不会被识别(例如,用于检查协议的一致性)。最终我做了这个:@objc public protocol AgedAnimal: Aged, Animal {} - balthisar

2
自从Swift 3以来,您可以使用"typealias"创建符合多个协议的类型:

"自从Swift 3以来,您可以使用"typealias"创建符合多个协议的类型:"
typealias AgedAnimal = Animal & Aged

所以你的代码将变成:

这样:

extension Moveable where Self: AgedAnimal {
    // ...
}

最初的回答:或者像这样:

typealias Live = Aged & Moveable

extension Animal where Self: Live {
    // ...
}

0

将协议变为引用类型

extension Moveable: AnyObject {}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接