Swift泛型和子类

时间:2017-08-11 07:41:22

标签: arrays swift generics

我的问题可能很简单,但它让我感到困惑: 想象一下,我有一系列不同的对象,它们都有一个共同的父类" MyClass"。

var values = [MyClass]()

然而,他们都有自己的特定子类,例如" MyClassSubclass"。

values.append(MyClassSubclass())

我现在想要创建一个泛型方法,让我返回此数组中第一个类型为MyClassSubclass的对象。我想阻止转换对象,但是有一个泛型方法,它将子类对象作为T参数,并在此数组中返回第一次出现的子类T.

我想到了类似的东西(但肯定不起作用):

func getFirst<T: MyClass>(_ ofType : T.Type) -> T?

我想我只是被卡住而且我不知道该搜索什么,所以如果有人能帮助我,我会非常感激。

修改 基于以上值的示例:

class MyClass {}
class MyClassSubclass : MyClass {}
class MyClassSubclass2 : MyClass{}

var values = [MyClass]()
values.append(MyClassSubclass())
values.append(MyClassSubclass2())

//Return the first class element appearing here as a subclass type
func getFirst<T>(_ ofType : T.Type) -> T?{}

由于

3 个答案:

答案 0 :(得分:5)

一种方法是遍历数组并使用可选绑定 检查元素是否属于给定类型:

func getFirst<T: MyClass>(ofType: T.Type) -> T? {
    for elem in values {
        if let item = elem as? T {
            return item
        }
    }
    return nil
}

使用for case模式{/ 1}}可以简化此操作:

as

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

flatMap

如果数组可能很大并且您想避免创建 中间数组然后你可以使用func getFirst<T: MyClass>(ofType: T.Type) -> T? { return values.flatMap { $0 as? T }.first }

lazy

作为数组扩展方法,这将是

func getFirst<T: MyClass>(ofType: T.Type) -> T? {
    return values.lazy.flatMap { $0 as? T }.first
}

答案 1 :(得分:1)

这有点像滥用泛型,但这是一个扩展:

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

然后可以将该方法称为let first = values.getFirst(MyClassSubclass.self)

我个人更喜欢简单地为了清晰度而内联:

let first = values.first(where: { type(of: $0) == MyClassSubclass.self }) as? MyClassSubclass

答案 2 :(得分:1)

如果您想使用不推荐使用的全局功能,请尝试使用

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)

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