gpt4 book ai didi

arrays - 检查元类型是否为元素类型为 MyProtocol 的数组

转载 作者:可可西里 更新时间:2023-11-01 01:22:50 26 4
gpt4 key购买 nike

我需要为不同的类(class)做不同的事情。例如我创建了协议(protocol)

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 的问题

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())

在我的 Playground 控制台中,数组 A3 , 我看到 Array<MyDto> ,但我希望像 Array<Any> 这样的数组的第一个返回.

如何检查 Array Element在哪里很亲切MappableProtocol

最佳答案

问题是 [MyDto]instances 可以自由转换为 [MappableProtocol][Any],这些实际上只是编译器在幕后进行的神奇转换(有关更多信息,请参阅 this Q&A)。

元类型值不存在相同的转换,这就是为什么 Swift 说 [MyDto].Type 不是 [MappableProtocol].Type 也不是[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>

(我删除了你的 API 类只是为了简化事情)

编译器将简单地在编译时解决要调用的重载,而不是让运行时跳过许多类型转换环节。


如果您坚持使用元类型值,一个可能的解决方案是为 Array 定义一个虚拟协议(protocol)以符合(参见例如 this similar Q&A ),然后我们可以将元类型值转换为。然后我们可以声明一个 elementType 静态要求以提取 ArrayElement.self 元类型值,然后我们可以检查类型的以确定数组可转换为什么。

例如,如果我们将Array定义并符合_ArrayProtocol:

protocol _ArrayProtocol {
static var elementType: Any.Type { get }
}

extension Array : _ArrayProtocol {
static var elementType: Any.Type {
return Element.self
}
}

我们现在可以像这样使用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>

关于arrays - 检查元类型是否为元素类型为 MyProtocol 的数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43127766/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com