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>