gpt4 book ai didi

swift - 如何快速检查对象是否属于动态类类型?

转载 作者:搜寻专家 更新时间:2023-10-30 22:07:16 25 4
gpt4 key购买 nike

我正在实现一个名为 ofType 的函数,它过滤掉给定类型的所有元素。

这是我的代码:

class Animal {}
class Mammal: Animal {}
class Monkey: Mammal {}
class Pig: Mammal {}
class Human: Mammal {}

extension Array {
func ofType<T>(_ metatype: T.Type) -> [T] {
return flatMap { type(of: $0) == metatype ? $0 as? T : nil }
// return flatMap { $0 as? T } // This is not working as the T is always the static type of the parameter, which is Animal in this example.
// return flatMap { $0 as? metatype } // This is not working either because of the grammar restriction.
}
}

let animals = [Monkey(), Pig(), Human(), Mammal(), Animal()]
func animalType() -> Animal.Type {
return Mammal.self
}
animals.ofType(animalType()).count // returns 1, expect to be 4.

在 Objc 中,我可以使用 isKindOf() 来检查对象是类的实例还是子类的实例。 swift isas 中也有类似的操作,但是它们后面的类型应该是静态类型,而不是动态类型值(例如我可以写 is Mammal ,但不是是 Mammal.self)。

我也不能使用类型参数 T,因为在这个例子中,T 等于 Animal,这不是我想要的.

你知道如何实现这个功能吗?

最佳答案

这行得通。只需在 flatMap 中使用 as? 即可。如果动物可以被施放,它将被返回,否则返回 nil 并且 flatMap 将其丢弃

class Animal {}
class Mammal: Animal {}
class Monkey: Mammal {}
class Pig: Mammal {}
class Human: Mammal {}

extension Array {
func ofType<T>() -> [T]
{
return flatMap { $0 as? T }
}
}

let animals = [Monkey(), Pig(), Human(), Mammal(), Animal()]
let monkeys: [Monkey] = animals.ofType() // A one element array
let mammals: [Mammal] = animals.ofType() // A four element array

如果您显式键入输出数组,编译器可以从上下文中推断出 T,否则您将 T 的类型作为参数传递但不在函数中使用它。


如果你希望能够动态检查类型,即你不知道在编译时要过滤的类型,你可以使用镜像。这是一个有点笨拙但确实有效的解决方案:

class Animal
{
func isInstance(of aType: Any.Type) -> Bool
{
var currentMirror: Mirror? = Mirror(reflecting: self)
while let theMirror = currentMirror
{
if theMirror.subjectType == aType
{
return true
}
currentMirror = theMirror.superclassMirror
}
return false
}
}
class Mammal: Animal {}
class Monkey: Mammal {}
class Pig: Mammal {}
class Human: Mammal {}


let animals = [Monkey(), Pig(), Human(), Mammal(), Animal()]

for aType in [Animal.self, Mammal.self, Monkey.self]
{
let result = animals.flatMap { $0.isInstance(of: aType) ? $0 : nil }
print("\(result)")
}

打印:

[__lldb_expr_12.Monkey, __lldb_expr_12.Pig, __lldb_expr_12.Human, __lldb_expr_12.Mammal, __lldb_expr_12.Animal]
[__lldb_expr_12.Monkey, __lldb_expr_12.Pig, __lldb_expr_12.Human, __lldb_expr_12.Mammal]
[__lldb_expr_12.Monkey]

编辑 根据 Sam 在评论中的建议,我想到上述方法最好放在协议(protocol)扩展中。

protocol TypeCheckable {}

extension TypeCheckable
{
func isInstance(of aType: Any.Type) -> Bool
{
var currentMirror: Mirror? = Mirror(reflecting: self)
while let theMirror = currentMirror
{
if theMirror.subjectType == aType
{
return true
}
currentMirror = theMirror.superclassMirror
}
return false
}
}

然后您可以通过使其符合协议(protocol)来将功能添加到任何 Swift 类型。

class Animal: TypeCheckable { ... }

extension String: TypeCheckable {}

关于swift - 如何快速检查对象是否属于动态类类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48535872/

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