3

在 Swift 2 中,我有以下协议

protocol Fightable {
    // return true if still alive, false if died during fight
    func fight (other: Fightable) -> Bool
}

protocol Stats {
    var defense: Int { get }
    var attack: Int { get }
}

我可以为 Fightable 实现一个协议扩展,以提供fight跨所有值类型的共享实现,Stats如果我将类型签名更改fight

func fight (other: Self) -> Bool

并将扩展实现为

extension Fightable where Self : Stats {
    func fight (other: Self) -> Bool {
        return self.defense > other.attack
    }
}

上述实现的问题在于它要求值类型相同(Humans can't fight Goblins)。我目前的目标是实现一个协议扩展,fight只要它们实现了 Stats,就可以为任何值类型组合提供默认实现。

以下代码

extension Fightable where Fightable : Stats {
    func fight (other: Fightable) -> Bool {
        return self.defense > other.attack
    }
}

产生错误

一致性要求中的“可战斗”类型不引用泛型参数或关联类型

如何确保其他 Fightable 类型也符合此扩展的统计信息?

我正在使用 Xcode 7 beta 1。

4

2 回答 2

1

对不起,我误解了你的问题。因此,如果我理解正确(希望如此),则不可能fight通过协议扩展(至少在这些约束下)获得该功能的默认实现。因为如果您想other符合Fightable并且Stats它不再是以前的功能,那么other可能是 any Fightable。所以它没有实现所需的功能。作为解决方法,我建议(采用您现有的代码):

protocol Fightable {
    // return true if still alive, false if died during fight
    func fight (other: Fightable) -> Bool
}

protocol Stats {
    var defense: Int { get }
    var attack: Int { get }
}

extension Fightable where Self : Stats {
    // directly conforming to the protocol
    func fight (other: Fightable) -> Bool {
        if let otherStat = other as? Stats {
            return self.defense > otherStat.attack
        }
        // providing a good way if other does not conform to Stats
        return false
    }
}
于 2015-06-17T21:21:21.377 回答
0

对我有用的一种方法是在您的 Fightable 协议中创建一个类型别名。所以你可以在你的协议扩展中限制战斗功能的参数。由于这种情况,您还必须使您的战斗功能通用(Fightable 不仅可以用作通用约束)。

在代码中它看起来像这样:

protocol Fightable {
    // make typealias
    typealias F = Fightable
    // make function generic
    func fight<F: Fightable>(other: F) -> Bool
}

protocol Stats {
    var defense: Int { get }
    var attack: Int { get }
}

// constraint F and Self
extension Fightable where F : Stats, Self: Stats {
    func fight(other: F) -> Bool {
        return self.defense > other.attack
    }
}

// example of an implementation
struct Human: Fightable {
    func fight<F: Fightable>(other: F) -> Bool {
        return true
    }
}
于 2015-06-17T20:24:21.170 回答