【问题标题】:Make class type a Dictionary key (Equatable, Hashable)使类类型成为字典键(Equatable、Hashable)
【发布时间】:2016-08-21 19:44:42
【问题描述】:

假设我有一个名为 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 是静态变量不可访问。

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

编辑:

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

let alienValue = livingCreatureForValue[Alien()]

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

【问题讨论】:

  • 为什么不让你的LivingCreature符合EquatableHashable并覆盖相关函数呢?
  • 因为那样我每次都必须分配 LivingCreature 以获得我的价值。这就是我想使用类类型而不是类实例的原因。
  • 我不明白你在说什么。如果您的类符合 Hashable 和 Equatable,那么所有子类都符合这些协议,您可以将这些类的实例用作字典键。
  • 你是说你想使用类对象作为你的字典键吗?听起来你做事的方式不对。如果您想要一个描述类的字符串,为什么不实现一个返回字符串并在子类中覆盖该函数的类函数。不需要字典
  • @Paulw11 我已经编辑了我的问题。关于做错事,设计代码有许多不同的选择,就我的目的而言,这个功能是我想要的。这就是我问一个问题的原因,看看是否有更好的做法来做我想要完成的事情。

标签: ios swift


【解决方案1】:

我假设您正在尝试类似:

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"

【讨论】:

  • ObjectIdentifier 正是我想要的,非常感谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-03
  • 1970-01-01
相关资源
最近更新 更多