使类类型为Dictionary键(Equatable,Hashable)

时间:2016-08-21 11:11:56

标签: ios swift

说我有一个名为LivingCreature的班级 以及从中继承的其他类:

  • Human

  • Dog

  • Alien

这就是我想要完成的事情:

let valueForLivingCreature = Dictionary<Alien, String>

并按如下方式访问:

let alienValue = livingCreatureForValue[Alien]

但这意味着该类应符合EquatableHashable,但类本身,而不是类实例。 我已经尝试了各种方法来实现这一点,但没有运气。

作为妥协,我想出的是:

typealias IndexingValue = Int
class LivingCreature {
     static var indexingValue: IndexingValue = 0 
}

然后我可以像这样使用类作为键:

 let livingCreatureForValue = Dictionary<IndexingValue, String>

访问:

let alienValue = livingCreatureForValue[Alien.indexingValue]

但是,这样就应该手动设置每个类的IndexingValue。 我想像这样从类本身做一个哈希:

class LivingCreature {
    static var indexingValue: IndexingValue {
        return NSStringFromClass(self).hash
    }
}

这是不可能的,因为self无法访问是静态var。

我的问题是,有没有更好的方法来解决这类问题?

修改

@ Paulw11问我为什么不让LivingCreature确认Equatable和Hashable, 原因是我无法通过类类型引用访问该值。  我每次都要分配一个实例:

let alienValue = livingCreatureForValue[Alien()]

我不想每次都找“Alien()”来找到一个值。 并且使用它的组件不关心livingCreature实例,只关心类类型。

1 个答案:

答案 0 :(得分:7)

我认为你正在尝试这样的事情:

let valueForLivingCreature = Dictionary<LivingCreature.Type, String>

let alienValue = valueForLivingCreature[Alien.self]

然后您可以使用ObjectIdentifier

class LivingCreature {
    class var classIdentifier: ObjectIdentifier {
        return ObjectIdentifier(self)
    }
    //...
}

class Human: LivingCreature {
    //...
}

class Dog: LivingCreature {
    //...
}

class Alien: LivingCreature {
    //...
}

let valueForLivingCreature: Dictionary<ObjectIdentifier, String> = [
    Human.classIdentifier: String(Human),
    Dog.classIdentifier: String(Dog),
    Alien.classIdentifier: String(Alien),
]

let alienValue = valueForLivingCreature[Alien.classIdentifier] //->"Alien"

但是在大​​多数用例中,当你想使用元类作为字典键时,你可以找到另一种方法:

class LivingCreature {
    class var classValue: String {
        return String(self)
    }
    //...
}

class Human: LivingCreature {
    //...
    //Override `classValue` if needed.
}

class Dog: LivingCreature {
    //...
}

class Alien: LivingCreature {
    //...
}

let alienValue = Alien.classValue //->"Alien"