used type only has generic functions extension constraint because associated swift generics protocols swift2 associated-types

type - swift variables



Protocolo Swift con error de tipo asociado asociado "Tipo no es convertible" (1)

El error ocurre porque ManagerReaderType en la función de read es solo un marcador de posición genérico para cualquier tipo que se ajuste a Reader y su ReaderValueType es igual al de ManagerReaderType . Entonces, el tipo real de ManagerReaderType no está determinado por la función en sí, sino que el tipo de la variable que se asigna declara el tipo:

let manager = Manager1() let reader1: Reader1? = manager.read() // ManagerReaderType is of type Reader1 let reader2: Reader2? = manager.read() // ManagerReaderType is of type Reader2

si devuelve nil , puede convertirse a cualquier tipo opcional para que siempre funcione.

Como alternativa, puede devolver un tipo específico de Reader de tipo:

protocol Manager { // this is similar to the Generator of a SequenceType which has the Element type // but it constraints the ManagerReaderType to one specific Reader typealias ManagerReaderType: Reader func read() -> ManagerReaderType? } class Manager1: Manager { func read() -> Reader1? { return Reader1() } }

Este es el mejor enfoque con protocolos debido a la falta de genéricos "verdaderos" (el siguiente no es compatible (todavía)):

// this would perfectly match your requirements protocol Reader<T: Value> { fun value() -> T } protocol Manager<T: Value> { func read() -> Reader<T>? } class Manager1: Manager<Value1> { func read() -> Reader<Value1>? { return Reader1() } }

Por lo tanto, la mejor solución sería hacer de Reader una clase genérica y las clases de Reader1 y Reader2 un tipo genérico específico:

class Reader<T: Value> { func value() -> T { // or provide a dummy value fatalError("implement me") } } // a small change in the function signature protocol Manager { typealias ManagerValueType: Value func read() -> Reader<ManagerValueType>? } class Reader1: Reader<Value1> { override func value() -> Value1 { return Value1() } } class Reader2: Reader<Value2> { override func value() -> Value2 { return Value2() } } class Manager1: Manager { typealias ManagerValueType = Value1 func read() -> Reader<ManagerValueType>? { return Reader1() } } let manager = Manager1() // you have to cast it, otherwise it is of type Reader<Value1> let a: Reader1? = manager.read() as! Reader1?

Esta implementación debería resolver su problema, pero ahora los Readers son tipos de referencia y se debe considerar una función de copia.

Creé 2 protocolos con tipos asociados. Un tipo conforme a Reader debería ser capaz de producir una instancia de un tipo conforme a Value .

La capa de complejidad proviene de un tipo que se ajusta al Manager debe ser capaz de producir una instancia concreta de Reader que produce un tipo específico de Value (ya sea Value2 o Value2 ).

Con mi implementación concreta de Manager1 me gustaría que siempre produzca Reader1 que a su vez produce instancias de Value1 .

¿Podría alguien explicar por qué?

"Reader1 no es convertible a ManagedReaderType?"

Cuando la línea errónea se cambia a (por ahora) return nil , todo se compila muy bien, pero ahora no puedo instanciar Reader1 o Reader2 .

Lo siguiente se puede pegar en un área de juegos para ver el error:

import Foundation protocol Value { var value: Int { get } } protocol Reader { typealias ReaderValueType: Value func value() -> ReaderValueType } protocol Manager { typealias ManagerValueType: Value func read<ManagerReaderType: Reader where ManagerReaderType.ReaderValueType == ManagerValueType>() -> ManagerReaderType? } struct Value1: Value { let value: Int = 1 } struct Value2: Value { let value: Int = 2 } struct Reader1: Reader { func value() -> Value1 { return Value1() } } struct Reader2: Reader { func value() -> Value2 { return Value2() } } class Manager1: Manager { typealias ManagerValueType = Value1 let v = ManagerValueType() func read<ManagerReaderType: Reader where ManagerReaderType.ReaderValueType == ManagerValueType>() -> ManagerReaderType? { return Reader1()// Error: "Reader1 is not convertible to ManagedReaderType?" Try swapping to return nil which does compile. } } let manager = Manager1() let v = manager.v.value let a: Reader1? = manager.read() a.dynamicType