将“Protocol”用作符合协议“Protocol”的具体类型不受支持。

5
我有以下的Swift代码:

protocol Animal {
var name: String { get }
}

struct Bird: Animal {
    var name: String
    var canEat: [Animal]
}

struct Mammal: Animal {
    var name: String
}

extension Array where Element: Animal {
    func mammalsEatenByBirds() -> [Mammal] {
        var eatenMammals: [Mammal] = []
        self.forEach { animal in
            if let bird = animal as? Bird {
                bird.canEat.forEach { eatenAnimal in
                    if let eatenMammal = eatenAnimal as? Mammal {
                        eatenMammals.append(eatenMammal)
                    } else if let eatenBird = eatenAnimal as? Bird {
                        let innerMammals = eatenBird.canEat.mammalsEatenByBirds()
                        eatenMammals.append(contentsOf: innerMammals)
                    }
                }
            }
        }
        return eatenMammals
    }
}

编译器不允许我编译,抱怨说:在递归调用函数mammalsEatenByBirds()的时候,使用“Animal”作为符合协议“Animal”的具体类型是不被支持的。我看到了一些其他的答案,但无法将我的问题与其中任何一个联系起来。

请阅读 http://stackoverflow.com/search?q=Using++as+a+concrete+type+conforming+to+protocol+is+not+supported 的结果。 - vadian
1
比较协议不符合自身? - 简单的修复方法只是将扩展名更改为extension Array where Element == Animal {...}。尽管如此,考虑到您仅使用'Bird'元素,您可能希望考虑将其设置为extension Sequence where Iterator.Element == Bird,并在调用之前执行(懒惰的)flatMap以仅过滤'Bird'元素。 - Hamish
谢谢,它起作用了。 - Muhammad Ali
1个回答

8

Fix是将Element: Animal替换为Element == Animal


如果你这样做,你必须显式地将 Bird 数组转换为 Animal。像这样:let mammals = (birds as Animal).mammalsEatenByBirds()。这很愚蠢(不是你的错,而是 Swift 的问题)。 - kelin

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