Próbuję zrozumieć, dlaczego, gdzie klauzula metody rodzajowej jest ignorowanyBłędna funkcja przeciążenia generic nazywa
Zrobiłem prosty przypadek użycia w Swift 3 (można skopiować kod na placu zabaw jeśli chcesz się z nim bawić):
//MARK: - Classes
protocol HasChildren {
var children:[Human] {get}
}
class Human {}
class SeniorHuman : Human, HasChildren {
var children: [Human] {
return [AdultHuman(), AdultHuman()]
}
}
class AdultHuman : Human, HasChildren {
var children: [Human] {
return [YoungHuman(), YoungHuman(), YoungHuman()]
}
}
class YoungHuman : Human {}
//MARK: - Generic Methods
/// This method should only be called for YoungHuman
func sayHelloToFamily<T: Human>(of human:T) {
print("Hello \(human). You have no children. But do you conform to protocol? \(human is HasChildren)")
}
/// This method should be called for SeniorHuman and AdultHuman, but not for YoungHuman...
func sayHelloToFamily<T: Human>(of human:T) where T: HasChildren {
print("Hello \(human). You have \(human.children.count) children, good for you!")
}
Ok, więc teraz uruchommy kilka testów. Jeśli mamy:
let senior = SeniorHuman()
let adult = AdultHuman()
print("Test #1")
sayHelloToFamily(of: senior)
print("Test #2")
sayHelloToFamily(of: adult)
if let seniorFirstChildren = senior.children.first {
print("Test #3")
sayHelloToFamily(of: seniorFirstChildren)
print("Test #4")
sayHelloToFamily(of: seniorFirstChildren as! AdultHuman)
}
Wyjście jest:
Test #1
Hello SeniorHuman. You have 2 children, good for you!
Test #2
Hello AdultHuman. You have 3 children, good for you!
Test #3
Hello AdultHuman. You have no children. But do you conform to protocol? true
//Well, why are you not calling the other method then?
Test #4
Hello AdultHuman. You have 3 children, good for you!
//Oh... it's working here... It seems that I just can't use supertyping
Cóż ... widocznie, gdyż klauzula protokół where
pracować, musimy zdać silny typ, który jest zgodny z protokołem w swojej definicja.
Samo użycie supertekstu nie wystarczy, nawet jeśli w teście nr 3 oczywiste jest, że dana instancja faktycznie odpowiada protokołowi HasChildren
.
Więc, czego tu brakuje, czy to po prostu niemożliwe? Czy masz kilka linków podających więcej informacji o tym, co się dzieje, lub więcej informacji na temat klauzul where
, podtypów i ogólnie ich zachowania?
Czytałem kilka przydatnych zasobów, ale nikt zdaje się mieć wyczerpującego wyjaśnienia, dlaczego to nie działa:
Cóż, to dość oczywiste, kiedy mówisz tak. Nie mogę uwierzyć, że tęskniłem za tym ... Myślę, że mój pomysł rekurencyjnych funkcji ogólnych nie działałby wtedy prawidłowo, gdybyśmy nie mogli uczynić ich dynamicznymi. –