Matching requirement type is not a generic parameter or related type

In Swift 2 I have the following protocols

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

      

I can implement a protocol extension for Fightable to provide a common implementation fight

for all value types that match Stats

if I change the type signature fight

to

func fight (other: Self) -> Bool

      

and implement the extension as

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

      

The problem with the above implementation is that it requires the value types to be the same ( Human

can't fight Goblin

s). My current goal is to implement a protocol extension that provides a standard implementation fight

for any combination of value types as long as they implement Stats.

The following code

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

      

Produces an error

The type "Combat" in the compliance requirement is not a generic or related type

How can I make sure the other Fightable type also matches the Stats for this extension?

I am using XCode 7 beta 1.

+3


source to share


2 answers


One way that works for me is to do titalias in your battle log. Thus, you can limit the parameter of the combat function in your protocol extension. Because of this situation, you also need to make your combat function generic (Fightable can only be used as a general limitation).

In code, it looks like this:



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

      

0


source


Sorry, but I misunderstood your problem. So if I understand you correctly (hopefully), it is not possible to get a standard implementation of a function by fight

extending the protocol (at least with these restrictions). Because if you want to other

match Fightable

and Stats

, it is no longer the previous function where it other

could be anything Fightable

. Therefore, it does not fulfill the required function. As a workaround, I would suggest (taking your existing code):



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

      

0


source







All Articles