Jeśli rozumiem to poprawnie, Swift może określić rzeczywisty rodzaj leków generycznych za pomocą różnych środków, w tym dopasowywania przez typ zwrotu. Ten sam (lub podobny) mechanizm służy do rozróżniania przeciążonych funkcji. Tak to działa zgodnie z oczekiwaniami:Swift rodzajowy wybór nie propaguje
func getValue<T>()->T? {
return nil
}
func getValue()->Int? {
return 13
}
let b: Int? = getValue()
Uruchamiając ten, b będą 13
. Pod względem technicznym oba sygnatury funkcji są dopasowane, ale te ostatnie są bardziej specyficzne dla żądanego typu zwrotu.
Dodajmy drugą funkcję i tunel zaproszeniu przez niego:
func getGetValue<T>()->T? {
return getValue()
}
let c: Int? = getGetValue()
Uruchamiając ten, c będzie nil
. W rzeczywistości kompilator wybierze ogólną implementację getValue(), która będzie wywoływana z getGetValue(), co nie jest tym, czego potrzebuję. IMHO, żądany typ zwracany powinien rozprzestrzeniać się za pośrednictwem drugiego generycznego, wybierając między dwiema implementacjami getValue(), powodując zachowanie takie samo jak w pierwszym przykładzie.
Czego mi brakuje? (Xcode 7.1)
Doskonałe znalezisko. Domyślam się, że typ "domniemany przez zwrot" nie działa, gdy istnieje kolejna warstwa abstrakcji. Wewnątrz 'getGetValue', kompilator nie ma pojęcia, że typ' T' jest, więc pierwsza funkcja jest jedyną, która pasuje. –
@ZoffDino To również moje przypuszczenie, ale nie rozumiem, dlaczego kompilator nie może propagować typów z dołu do góry. Z mojego punktu widzenia wygląda na błąd - ale nie jestem kompilatorem. Być może istnieje całkowicie uzasadniony powód takiego zachowania. Złożę radar, na wszelki wypadek. –
W blogu Swift znajduje się wpis [Bezpieczeństwo pamięci: zapewnienie wartości są definiowane przed użyciem] (https://developer.apple.com/swift/blog/?id=28), który omawia, jak daleko kompilator idzie, aby udowodnić poprawność programu. Myślę, że jest to trochę istotne dla twojego pytania –