У мене є невелика проблема. Мені потрібно вказати повернене значення для функції, яка може повертати кожну реалізацію протоколу. Наприклад:
Мій протокол:
protocol MyProtocol {
//some functions
}
Виконання:
class ClassA: MyProtocol {
}
class ClassB: MyProtocol {
}
Функція "проблема":
func getClassByString(_ name: String) -> MyProtocol.Type {
switch name {
case "a":
return ClassA.self
case "b":
return ClassB.self
default:
return ClassC.self
}
}
// EDIT: Тут мені потрібен результат
final class Mapper<N: MyProtocol> {
public func map() -> N?{
if let klass = N.self as? MyProtocol.Type {
return klass as? N
}
return nil
}
}
Використання:
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
Проблема в тому result
не справді ClassA.Type
, що має бути, це зараз MyProtocol.Type
і я не можу передати це наступній функції. Коли даю result
питоме значення ClassA.self
все працює. Я не можу це зробити as! ClassA.self
тому що я не знаю, чи має це бути ClassA
або ClassB
або Class9000
Тож питання. Чи існує інший тип повернення типу MyProtocol.Type
для функції getClassByString()
або зовсім інший спосіб отримати ClassA.Type
до result
?
Відповіді:
1 для відповіді № 1Я думаю, що ваша проблема тут не зовсім така, як ви описуєте - result
Вашого прикладу насправді здається ClassA.Type
на дитячому майданчику, але проблема, на яку я підозрюю, полягає в тому, що ви з ним будете робити далі. У вашому протоколі не сказано як такі типи мають бути створені загальним чином, тому повернутий тип не може Бути екземпляр.
Я зробив кілька змін у вашому прикладі, і зараз він працює ...
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