协议中使用的Swift Generic类型不起作用

时间:2017-05-24 02:32:27

标签: swift generics inheritance protocols

我将我的麻烦简化为一个关于使用Generic Type和protocol的小型演示。这是代码。

protocol Food {

}

class Meat: Food {

}

class Cake: Food {

}

protocol EatProtocol {
    func eat<T: Food>(_: T)
}

class Person: EatProtocol {
    func eat<T>(_: T) where T : Food {
        print("eat food")
    }
}

class Man: Person {
    override func eat<T>(_: T) where T : Meat {
        print("eat meat")
    }
}

class Woman: Person {
    override func eat<T>(_: T) where T : Cake {
        print("eat cake")
    }
}

let man = Man()
let woman = Woman()
let manyPeople: [EatProtocol] = [man, woman]

let meat = Meat()
let cake = Cake()
let manyFood: [Food] = [meat, cake]

for (index, people) in manyPeople.enumerated() {
    let food = manyFood[index]
    people.eat(food)//error: Cannot invoke 'eat' with an argument list of type '(Food)'
}

问题是我确信for循环项目得到正确的食物,但编译器给我错误

1 个答案:

答案 0 :(得分:1)

这里有一个根本问题:并非所有食客都可以吃各种食物。在这个特定示例中,我能想到的最好的方法是使用switch来枚举可能的组合,安全地投射并进行调用:

protocol Food {}
class Meat: Food {}
class Cake: Food {}

protocol Eater {
    func eat<T: Food>(_: T)
}

class Person: Eater {
    func eat<T>(_: T) where T: Food {
        print("eat food")
    }
}

class Man: Person {
    override func eat<T>(_: T) where T: Meat {
        print("eat meat")
    }
}

class Woman: Person {
    override func eat<T>(_: T) where T : Cake {
        print("eat cake")
    }
}

let eaters: [Eater] = [Man(), Woman()]
let foods: [Food] = [Cake(), Cake()]

for (food, eater) in zip(foods, eaters) {
    switch (food, eater) {
        case let (meat as Meat, man as Man): man.eat(meat)
        case let (cake as Cake, woman as Woman): woman.eat(cake)
        //...
        default:
            print("\(eater) (of type: \(type(of: eater))) cannot eat \(food) (of type: \(type(of: food)))")
            continue
    }
}