Arrays 检查元类型是否为MyProtocol类型的元素类型的数组
我需要为不同的班级做不同的事情。例如,我创建了协议Arrays 检查元类型是否为MyProtocol类型的元素类型的数组,arrays,swift,generics,Arrays,Swift,Generics,我需要为不同的班级做不同的事情。例如,我创建了协议 protocol ResponseProtocol { associatedtype ResponseType: Any } protocol MappableProtocol { init(map: String) } 我正在将我的数据类MyDto class MyDto: MappableProtocol { required init(map: String) { } } 和3个不同的反应类 class A1
protocol ResponseProtocol {
associatedtype ResponseType: Any
}
protocol MappableProtocol {
init(map: String)
}
我正在将我的数据类MyDto
class MyDto: MappableProtocol {
required init(map: String) { }
}
和3个不同的反应类
class A1: ResponseProtocol {
typealias ResponseType = String
}
class A2: ResponseProtocol {
typealias ResponseType = MyDto
}
class A3: ResponseProtocol {
typealias ResponseType = [MyDto]
}
现在我需要根据ResponseType
做不同的事情
我尝试了这段代码,但是我遇到了Array
s的问题
class API {
func test<T: ResponseProtocol>(a: T) -> String {
if T.ResponseType.self is String.Type {
return "String"
}
if T.ResponseType.self is MappableProtocol.Type {
return "MappableProtocol"
}
if T.ResponseType.self is [Any].Type {
return "Array<Any>" // Why is this false?
}
if T.ResponseType.self is [MappableProtocol].Type {
return "Array<MappableProtocol>" //Why is this false?
}
if T.ResponseType.self is [MyDto].Type {
return "Array<MyDto>" // Why is only this true?
}
return "notFound"
}
}
let api = API()
let t1 = api.test(a: A1())
let t2 = api.test(a: A2())
let t3 = api.test(a: A3())
类API{
func测试(a:T)->字符串{
如果T.ResponseType.self是String.Type{
返回“字符串”
}
如果T.ResponseType.self是MappableProtocol.Type{
返回“MappableProtocol”
}
如果T.ResponseType.self是[Any]。请键入{
返回“Array”//为什么为false?
}
如果T.ResponseType.self是[MappableProtocol]。请键入{
返回“Array”//为什么为false?
}
如果T.ResponseType.self是[MyDto],请键入{
返回“Array”//为什么只有这样?
}
返回“未找到”
}
}
设api=api()
设t1=api.test(a:A1())
设t2=api.test(a:A2())
设t3=api.test(a:A3())
在我的游乐场控制台中,对于数组A3
,我看到了array
,但我希望像array
这样的数组会第一次返回
如何检查数组
,其中元素
属于MappableProtocol
?问题在于,虽然[MyDto]
的实例可以自由转换为[MappableProtocol]
和[Any]
,但是,这些实际上只是编译器在幕后进行的神奇转换(有关更多信息,请参阅)
元类型值不存在相同的转换,这就是为什么Swift说a[MyDto].Type
不是[MappableProtocol].Type
或a[Any].Type
——它们是不相关的元类型
在您的情况下,最简单的解决方案可能就是忘记使用元类型,而只是声明test(a:)
的不同重载来处理不同的ResponseType
类型
// 'default' overload of test(a:)
func test<T : ResponseProtocol>(a: T) -> String {
return "notFound"
}
func test<T : ResponseProtocol>(a: T) -> String where T.ResponseType == String {
return "String"
}
func test<T : ResponseProtocol>(a: T) -> String where T.ResponseType : MappableProtocol {
return "MappableProtocol"
}
func test<T : ResponseProtocol>(a: T) -> String where T.ResponseType == [MyDto] {
return "Array<MDto>"
}
// overload of test(a:) that accepts a type that conforms to ResponseProtocol, where the
// ResponseType is an Array with arbitrary Element type.
func test<T : ResponseProtocol, ResponseTypeElement : MappableProtocol>(a: T) -> String
where T.ResponseType == [ResponseTypeElement]
{
return "Array<MappableProtocol>"
}
print(test(a: A1())) // String
print(test(a: A2())) // MappableProtocol
print(test(a: A3())) // Array<MyDto>
// A MappableProtocol with a ResponseType that conforms to MappableProtocol,
// but isn't MyDto.
class Foo : MappableProtocol { required init(map: String) { } }
class A4 : ResponseProtocol { typealias ResponseType = [Foo] }
print(test(a: A4())) // Array<MappableProtocol>
我们现在可以像这样使用test(a:)
:
func test<T : ResponseProtocol>(a: T) -> String {
if T.ResponseType.self is String.Type {
return "String"
}
if T.ResponseType.self is MappableProtocol.Type {
return "MappableProtocol"
}
// attempt to cast the T.ResponseType.self metatype value to the existential metatype
// type _ArrayProtocol.Type (i.e a type that conforms to _ArrayProtocol),
// in this case, that's only ever Array.
if let responseType = T.ResponseType.self as? _ArrayProtocol.Type {
// switch on the element type, attempting to cast to different metatype types.
switch responseType.elementType {
case is MyDto.Type:
return "Array<MyDto>"
case is MappableProtocol.Type:
return "Array<MappableProtocol>"
default:
return "Array<Any>"
}
}
return "notFound"
}
print(test(a: A1())) // String
print(test(a: A2())) // MappableProtocol
print(test(a: A3())) // Array<MyDto>
print(test(a: A4())) // Array<MappableProtocol>
func测试(a:T)->字符串{
如果T.ResponseType.self是String.Type{
返回“字符串”
}
如果T.ResponseType.self是MappableProtocol.Type{
返回“MappableProtocol”
}
//尝试将T.ResponseType.self元类型值强制转换为存在元类型
//类型_ArrayProtocol.type(即符合_ArrayProtocol的类型),
//在本例中,这是唯一一个数组。
如果let responseType=T.responseType.self as?\u ArrayProtocol.Type{
//打开元素类型,尝试转换为不同的元类型。
开关响应Type.elementType{
案例为MyDto。类型:
返回“数组”
病例为MappableProtocol。类型:
返回“数组”
违约:
返回“数组”
}
}
返回“未找到”
}
打印(测试(a:A1())//字符串
打印(测试(a:A2())//MappableProtocol
打印(测试(a:A3())//数组
打印(测试(a:A4())//数组
你能帮我查字典吗。通过示例func sortDescriptor(a:T)->字符串where T.Element.value:ValueElement{return“Dictionary”}
,我绑定了这段代码。但这不是worked@EvGeniyIlyin字典
既不是类也不是协议,因此不能将其用作泛型约束。现在还不清楚您在本文中对ValueElement
的确切含义是什么–它是现有的协议吗?如果是这样,您可能指的是func-sortDescriptor(a:[String:Value])->Value:ValueElement所在的字符串。请记住:使用通用占位符来描述变化的类型–在本例中,字典
是常量,因此它被定义为参数类型,而不是通用占位符。如果您只是指“具有字符串
键的字典,但任何类型的值”–您的意思是说funct sortddescriptor(a:[String:Value])->String
@EvGeniyIlyin但实际上,如果你有新问题,你应该(当然,先做一些研究之后)而不是在评论中作为后续问题提问。
func test<T : ResponseProtocol>(a: T) -> String {
if T.ResponseType.self is String.Type {
return "String"
}
if T.ResponseType.self is MappableProtocol.Type {
return "MappableProtocol"
}
// attempt to cast the T.ResponseType.self metatype value to the existential metatype
// type _ArrayProtocol.Type (i.e a type that conforms to _ArrayProtocol),
// in this case, that's only ever Array.
if let responseType = T.ResponseType.self as? _ArrayProtocol.Type {
// switch on the element type, attempting to cast to different metatype types.
switch responseType.elementType {
case is MyDto.Type:
return "Array<MyDto>"
case is MappableProtocol.Type:
return "Array<MappableProtocol>"
default:
return "Array<Any>"
}
}
return "notFound"
}
print(test(a: A1())) // String
print(test(a: A2())) // MappableProtocol
print(test(a: A3())) // Array<MyDto>
print(test(a: A4())) // Array<MappableProtocol>