一致性要求中的类型不引用泛型参数或关联类型

Type in conformance requirement does not refer to a generic parameter or associated type

在Swift2中我有以下协议

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 }
}

如果我将 fight 的类型签名更改为

func fight (other: Self) -> Bool

并将扩展实现为

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

上面实现的问题在于它要求值类型必须相同(Humans不能打Goblins)。我目前的目标是实现一个协议扩展,为任何值类型的组合提供 fight 的默认实现,只要它们实现 Stats.

如下代码

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

产生错误

Type 'Fightable' in conformance requirement does not refer to a generic parameter or associated type

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

我正在使用 Xcode 7 beta 1。

对我有用的一种方法是在您的 Fightable 协议中创建类型别名。所以你可以在你的协议扩展中约束 fight 函数的参数。由于这种情况,您还必须使战斗功能通用(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
    }
}

对不起,我误解了你的问题。因此,如果我对你的理解是正确的(希望如此),则不可能通过协议扩展(至少在这些约束下)获得 fight 函数的默认实现。因为如果你想要 other 符合 FightableStats 它不再是以前的函数,其中 other 可以是任何 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
    }
}