Il problema sta nel confondere un segnaposto generico vincolato da un protocollo, con il protocollo stesso. Ecco un esempio più semplice, simile al tuo codice, per provare e chiarire:
// first, define a protocol and two structs that conform to it
protocol P { }
struct S1: P { }
struct S2: P { }
// now, a function that returns an object in the form
// of a reference to protocol P
func f() -> P {
// S1 conforms to P so that’s fine
return S1()
}
// ok all well and good, this works fine:
let obj = f()
// now, to do something similar to your example code,
// declare a generic function that returns a generic
// placeholder that is _constrained_ by P
// This will NOT compile:
func g<T: P>() -> T { return S1() }
Perché questo non viene compilato?
Il modo funzioni generiche lavoro è che al momento della compilazione, quando si chiama la funzione, il compilatore decide quale digitare il segnaposto T
deve essere, e poi si scrive una funzione con tutte le occorrenze di T
sostituiti con quel tipo .
Quindi, con l'esempio di seguito, T
dovrebbe essere sostituito da S1
:
let obj1: S1 = g()
// because T needs to be S1, the generic function g above is
// rewritten by the compiler like this:
func g() -> S1 { return S1() }
Questo sembra OK. Tranne, e se volessimo T
essere S2
? S2
è conforme a P
quindi è un valore perfettamente legittimo per T
. Ma come potrebbe funzionare:
// require our result to be of type S2
let obj2: S2 = g()
// so T gets replaced with S2… but now we see the problem.
// you can’t return S1 from a function that has a return type of S2.
// this would result in a compilation error that S2 is not
// convertible to S1
func g() -> S2 { return S1() }
Ecco l'origine del messaggio di errore che si sta ottenendo. Il segnaposto A
può sostituire qualsiasi tipo conforme a Protocol
, ma si sta tentando di restituire un specifico tipo (AClass
) conforme a tale protocollo. Quindi non ti lascerà fare.
Si dichiara un protocollo che ha un tipo _Generic_ ValueType'. Quindi, per conformarsi al protocollo stesso, si deve avere 'ValueType == String'. Quindi 'ValueType' non è destinato a essere _generico_. Si noti che 'String' non è un protocollo, ma un tipo concreto. –