Ich bin in einem Problem, wenn ich versuche, Self
als Teil einer where
Klausel in einer generischen Funktion, die Teil eines Protokolls ist zu verwenden.Fehler bei der Verwendung von Self in generische Funktion where-Klausel
Zum Beispiel sagen, ich habe dieses Protokoll und diese generische Funktion definiert:
protocol Animal {
associatedtype FoodSource
func eat(_ food:FoodSource)
}
// The where clause specifies that T2 must conform to
// whatever type is T1's FoodSource associated type
func feed<T1: Animal, T2>(animal:T1, food:T2) where T2 == T1.FoodSource {
animal.eat(food)
}
Der Funktion-Feed verwendet die klammert Aussage zu erklären, dass der erste Parameter mit dem Animal
Protokoll entsprechen. Es verwendet die -Klausel, um zu deklarieren, dass der Typ des zweiten Parameters dem zugeordneten Typ des ersten Parameters entsprechen muss.
Es ist möglich, Klassen zu erstellen, die den Anforderungen dieser generischen Funktion entsprechen und alles funktioniert perfekt. Zum Beispiel:
protocol Meat {}
protocol Vegetable {}
class Rabbit : Animal {
typealias FoodSource = Vegetable
func eat(_ food:FoodSource) {
print("the Rabbit ate the \(type(of:food))")
}
}
class Lion : Animal {
typealias FoodSource = Meat
func eat(_ food:FoodSource) {
print("the Lion ate the \(type(of:food))")
}
}
class Carrot : Vegetable {}
class Steak : Meat {}
class ChickenSalad : Meat, Vegetable {}
// works because Carrot conforms to Vegetable
// prints: "the Rabbit ate the Carrot"
feed(animal: Rabbit(), food: Carrot())
// works because Steak conforms to Meat
// prints: "the Lion ate the Steak"
feed(animal: Lion(), food: Steak())
// works because ChickenSalad conforms to Meat
// prints: "the Lion ate the ChickenSalad"
feed(animal: Lion(), food: ChickenSalad())
// works because ChickenSalad conforms to Vegetable
// prints: "the Rabbit ate the ChickenSalad"
feed(animal: Rabbit(), food: ChickenSalad())
So weit so gut.
Allerdings, wenn ich das gleiche Muster von Generika im Rahmen eines Protokolls implementieren, ist es nicht mehr funktioniert:
protocol Food {
func feed<T:Animal>(to:T) where Self == T.FoodSource
}
extension Food {
func feed<T:Animal>(to animal:T) where Self == T.FoodSource {
animal.eat(self)
}
}
class SteakSalad : Food, Meat, Vegetable {}
SteakSalad().feed(to: Lion())
Wenn er ausgeführt wird, wird dieser Block den folgenden Fehler führt:
error: generic parameter 'T' could not be inferred
SteakSalad().feed(to: Lion())
^
Ist Gibt es einen Weg, das gewünschte Verhalten zu erreichen?
https://stackoverflow.com/questions/36810270/swift-protocols-with-associated-type-requirement-and-default-implementation – suhit
Vielleicht bin ich dick, aber ich bin mir nicht sicher, genau, wie dies für meine gilt Fall. Ich weiß, dass die Beispiele inhaltlich sehr ähnlich sind, aber es scheint ein separates Thema zu sein. Im Fall des verknüpften Posts funktioniert Typinferenz nicht mehr auf "Kuh", da der zugehörige Typ für "Kuh.Food" ohne diese Methodensignatur nicht bestimmt werden kann. Im Fall meines Beispiels verstehe ich nicht, warum der Typ nicht direkt aus dem angegebenen Parameter (in diesem Fall "Löwe") abgeleitet werden würde. – sak