Tengo un pequeño problema. Necesito especificar un valor de retorno para una función que pueda devolver cada implementación de un Protocolo. Por ejemplo:
Mi protocolo
protocol MyProtocol {
//some functions
}
Implementaciones:
class ClassA: MyProtocol {
}
class ClassB: MyProtocol {
}
La función "problema":
func getClassByString(_ name: String) -> MyProtocol.Type {
switch name {
case "a":
return ClassA.self
case "b":
return ClassB.self
default:
return ClassC.self
}
}
//EDITAR: Aquí es donde necesito el resultado
final class Mapper<N: MyProtocol> {
public func map() -> N?{
if let klass = N.self as? MyProtocol.Type {
return klass as? N
}
return nil
}
}
Uso:
let className = "a" //this String comes from a JSON
let result = getClassByString(className)
let mappingResult = Mapper<result>().map() //undeclared identifier "result" error
let mappingResult = Mapper<ClassA>().map() //works but i do not know if it is ClassA
El problema es ese result
no es realmente ClassA.Type
, lo que debería ser, es ahora MyProtocol.Type
y no puedo pasar esto a la siguiente función. Cuando doy result
el valor específico de ClassA.self
Todo funciona. No puedo enviarlo a as! ClassA.self
porque no se si tiene que ser ClassA
o ClassB
o Class9000
Entonces la pregunta es. ¿Existe otro tipo de retorno como MyProtocol.Type
para la función getClassByString()
o una forma completamente diferente de obtener ClassA.Type
a result
?
Respuestas
1 para la respuesta № 1Creo que su problema aquí no es exactamente como lo describe: el result
de su ejemplo en realidad parece ser un ClassA.Type
en Playground, pero el problema que sospecho es qué haces con él a continuación. Tu protocolo no dice cómo tales tipos deben instanciarse de manera genérica, por lo que el tipo devuelto no puede ser instanciado.
Hice algunos cambios en tu ejemplo y ahora funciona ...
protocol MyProtocol {
//some functions
init() // To instantiate generically, there MUST be an accepted pattern for init()
}
class ClassA: MyProtocol {
required init() {}
}
class ClassB: MyProtocol {
required init() {}
}
class ClassC: MyProtocol {
required init() {}
}
func getClassByString(_ name: String) -> MyProtocol.Type {
switch name {
case "a":
return ClassA.self
case "b":
return ClassB.self
default:
return ClassC.self
}
}
let className = "a" //this String comes from a JSON
let result = getClassByString(className) // ClassA.Type
let a = result.init() // ClassA