Arrays Swift泛型和子类

Arrays Swift泛型和子类,arrays,swift,generics,Arrays,Swift,Generics,我的问题可能很简单,但它让我有点困惑: 假设我有一个不同对象的数组,它们都有一个共同的父类“MyClass”。 然而,它们都有自己的特定子类,例如“MyClassSubclass” 现在我想创建一个通用方法,返回这个数组中的第一个对象,它的类型是MyClassSubclass。我想阻止强制转换对象,但是有一个通用方法,它将子类对象作为T参数,并返回这个数组中第一个出现的子类T 我想到了这样的事情(但肯定行不通): func getFirst(uoftype:T.Type)->T? 我想我只是

我的问题可能很简单,但它让我有点困惑: 假设我有一个不同对象的数组,它们都有一个共同的父类“
MyClass
”。

然而,它们都有自己的特定子类,例如“
MyClassSubclass

现在我想创建一个通用方法,返回这个数组中的第一个对象,它的类型是
MyClassSubclass
。我想阻止强制转换对象,但是有一个通用方法,它将子类对象作为T参数,并返回这个数组中第一个出现的子类T

我想到了这样的事情(但肯定行不通):

func getFirst(uoftype:T.Type)->T?
我想我只是被卡住了,我不知道该找什么,所以如果有人能帮助我,我将不胜感激

根据上述值编辑示例:

类MyClass{}
类MyClassSubclass:MyClass{}
类MyClassSubClass 2:MyClass{}
变量值=[MyClass]()
values.append(MyClassSubclass())
append(MyClassSubClass 2())
//返回此处作为子类类型出现的第一个类元素
func getFirst(ofType:T.Type)->T?{}

谢谢

这感觉有点像滥用仿制药,但这里有一个扩展:

extension Array where Element == MyClass {
    func getFirst<T>(_ ofType: T.Type) -> T? {
        return self.first(where: { ofType == type(of: $0) }) as? T
    }
}

如果您想使用不推荐使用的全局函数,请尝试以下操作

func getFirst<T>(ofType: T.Type) -> T? where T: MyClass {
  for value in values where value is T {
    return value as? T
  }
  return nil
}

let first = getFirst(ofType: MyClassSubclass2.self)
func getFirst(ofType:T.Type)->T?T:MyClass在哪里{
对于值中的值,其中值为T{
返回值为?T
}
归零
}
let first=getFirst(类型:myclasssubclass 2.self)

对于Swift,第一个答案应该更好。

一种方法是迭代数组并使用可选绑定 要检查元素是否属于给定类型,请执行以下操作:

func getFirst<T: MyClass>(ofType: T.Type) -> T? {
    for elem in values {
        if let item = elem as? T {
            return item
        }
    }
    return nil
}
另一种方法是使用
flatMap
查找给定项目的所有项目 键入并返回第一个:

func getFirst<T: MyClass>(ofType: T.Type) -> T? {
    return values.flatMap { $0 as? T }.first
}
作为数组扩展方法,这将是

extension Array {
    func getFirst<T>(ofType: T.Type) -> T? {
        return flatMap { $0 as? T }.first
    }
}
扩展数组{
func getFirst(ofType:T.Type)->T{
首先返回flatMap{$0作为?T}
}
}

这看起来相当平滑,即使“?”转换比使用“if let”结构慢。但是你认为为什么不推荐这个函数呢?主要是因为它不适合重用,所以“扩展数组”更好。不过,为了澄清这一点,我喜欢扩展方式。它将是触摸框架的一部分,框架用户应能够轻松检索对象类型的第一个实例。这就是我想要这个的原因。因此,由于需要公共范围,扩展将是不好的。另外,您的第二种方法也不起作用,因为它将负载转移给框架用户(我说得对吗?)-为什么框架中的扩展不好?很多框架使用内置Swift和UIKit类型的扩展。我喜欢你的方法。您认为哪一个最快返回第一个事件?@binloan:我的猜测是for循环最快,必须进行测量和比较。但我建议首先检查这部分的性能是否对你的应用程序至关重要。如果阵列不是很大,那么我怀疑会有很大的差异。好的,我会测试一下。我的阵列目前不是很大,但这可能会在将来发生,我希望有一个适当的实现。+1获得全面的答案。而@binloan,for循环可能会更快(平均而言),因为
flatMap
s不会使操作短路。@xoudini:
lazy.flatMap
返回一个“lazy collection”,这样会短路,但开销更大。所以它取决于数组的大小。
let first = values.first(where: { type(of: $0) == MyClassSubclass.self }) as? MyClassSubclass
func getFirst<T>(ofType: T.Type) -> T? where T: MyClass {
  for value in values where value is T {
    return value as? T
  }
  return nil
}

let first = getFirst(ofType: MyClassSubclass2.self)
func getFirst<T: MyClass>(ofType: T.Type) -> T? {
    for elem in values {
        if let item = elem as? T {
            return item
        }
    }
    return nil
}
func getFirst<T: MyClass>(ofType: T.Type) -> T? {
    for case let item as T in values {
        return item
    }
    return nil
}
func getFirst<T: MyClass>(ofType: T.Type) -> T? {
    return values.flatMap { $0 as? T }.first
}
func getFirst<T: MyClass>(ofType: T.Type) -> T? {
    return values.lazy.flatMap { $0 as? T }.first
}
extension Array {
    func getFirst<T>(ofType: T.Type) -> T? {
        return flatMap { $0 as? T }.first
    }
}