【问题标题】:Search array for object of provided type搜索提供类型对象的数组
【发布时间】:2015-03-02 18:30:36
【问题描述】:

我有一组动物。我想搜索某个子类类型。 Animals 数组将永远只包含每个子类类型之一。我尝试了以下方法,但不起作用。我收到一个编译错误,指出:“animalType 不是类型”。

public static func getAnimal<T: Animal>(animalType: T.type) -> Animal {
    for animal in self.animals {
        if animal is animalType {
            return animal
        }
    }
}

这在 Swift 中可行吗?

我想这样称呼它......

AnimalServices.getAnimal(Dog)

【问题讨论】:

  • 你可以做一个 if let cast 作为一个类型,如果它失败了那么这个动物不是那个类型
  • 我刚试过。 "if let a = animal as animalType { }" 编译器仍然抱怨 animalType 不是类型。我在搞砸语法吗?

标签: ios arrays swift generics


【解决方案1】:

这是一个简化的示例,请注意我返回一个可选的 Animal,因为搜索可能会失败(编译器不知道您将始终只有一种该类型的动物):

class Animal {
    let name: String

    init(name: String) {
        self.name = name
    }
}

class Cat: Animal {
    init() {
        super.init(name: "Cat")
    }
}

class Dog: Animal {
    init() {
        super.init(name: "Dog")
    }
}

struct Zoo {
    static var animals: [Animal] = []

    static func getAnimal<T: Animal>(animalType: T.Type) -> Animal? {
        for animal in animals {
            if animal is T {
                return animal
            }
        }
        return nil
    }
}

Zoo.animals.append(Cat())

Zoo.getAnimal(Cat) // Returns the cat as optional
Zoo.getAnimal(Dog)

简单地说,T 是您的泛型类型。 T.Type 声明您将 T 类型作为参数传递。

【讨论】:

  • 我很接近。 ;) 这正是我想要的。谢谢!
  • 或者作为一个不错的单行:return animals.filter { $0 is T }.first。虽然性能较差。
【解决方案2】:

您可以使用标识运算符=== 来检查数组元素的类型是否等于泛型类型:

if animal.dynamicType === animalType {
    return animal
}

【讨论】:

  • 不,你不能。编译器会抛出错误:“二元运算符'==='不能应用于'Animal.Type'和'T'类型的操作数”
  • @blacksquare 你一定做错了——它在故事板中完美运行,而且我没有在代码 sn-p 中使用T...
  • 我刚刚在 swift 1.1 中测试了你的代码,它可以工作。我正在使用 swift 1.2 进行测试,但它抛出了一个错误——所以以后要小心。我正在使用我用来与返回的字符串值进行比较的语法,这是一个有效的比较,因为它们都是字符串。无论如何,该问题的最佳答案是简单地检查is T
  • 您的解决方案有效,但我更喜欢@Matteo Piombo 的解决方案。谢谢!
  • @blacksquare 我现在在 1.2 上进行了测试,它似乎可以工作 - 如上所述,我同意你的最后陈述:)
【解决方案3】:

您不能对未知类型使用 isas 语法。只要AnimalNSObject 的子类,就可以使用NSObject 的kindOfClass 方法来完成您要查找的类型反射:

class Animal: NSObject {

    class func getAnimalOfType<T: Animal>(animals: [Animal], animalType: T.Type) -> Animal? {
        for animal in animals {
            if animal.isKindOfClass(animalType) {
                return animal
            }
        }
        return nil
    }

}

class Zebra: Animal { }
class Whale: Animal { }
var animals = [Zebra(), Whale()]
Animal.getAnimalOfType(animals, animalType: Zebra.self)

如果 Animal 不是 NSObject 的子类型,您可以随时这样做——但对我来说这似乎有点 hacky:

 if "\(animal.dynamicType)" == "\(animalType)" {
      return animal
 }

【讨论】:

    【解决方案4】:
    struct Test<T: Hashable> {
    
        static func test(t: Any) {
            println(t is T)
        }
    }
    
    Test<Int>.test(3)
    

    在此示例中,我将类型(在我的情况下为 Int,在您的情况下为 animalType)传递给结构,并将变量(我的 Int(3),您的动物)作为静态函数测试的参数传递。我用了 T: Hashable,你会想用 T: Animal 来测试。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-09-22
      • 1970-01-01
      • 2011-10-20
      • 1970-01-01
      • 2021-01-20
      相关资源
      最近更新 更多