首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >是否可以在Swift中使用Type作为字典键?

是否可以在Swift中使用Type作为字典键?
EN

Stack Overflow用户
提问于 2017-10-18 15:38:50
回答 2查看 1.7K关注 0票数 3

我正在建造一个农场,那里所有可以生长的东西都符合可生长协议。当你种植一种植物时,你称它为“功能”:

myFarm.planting<T: Growable>(qty: Int, of: T.Type) -> Farm

现在,我希望农场的每个实例都有一个字典实例var,如下所示:

var crops = [Growable.Type: Int]

问题是,即使我使Growable协议继承Hashable,这也无助于Growable类型成为Hashable。

换句话说,即使我向Growable添加了如下扩展:

代码语言:javascript
复制
extension Growable {
    static func hashValue {
        // return some hash
    }
}

..。但是,Growable类型是不可接受的,因为Hashable协议只涉及类型的实例,而不涉及类型本身。

好吧,通常我会放弃,说:“我太蠢了,别再这样做了。”

然而,这是Swift,所以我想一定有一种方法可以使语言顺应我的意愿,无论是制定一个新的StaticHashable协议,然后用新的下标方法扩展字典类型,接受它,或者修改Swift的源代码本身,然后向进化论列表做一个介绍。

但在我走上这两条路之前,我认为明智的做法是问你们天才们是否已经有办法去做我想做的事,或者这样做是否非常愚蠢,你会给我一个明显优越的方法,那就是我一直以来都是愚蠢得令人难以置信的愚蠢。

注意:我的观点是,类型本身应该能够静态地遵守其功能不被声明为静态的协议,因为为什么消息的发送方应该关心响应的实体是不朽的上帝还是以某种上帝的形象创建的短暂的生物?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-10-18 19:58:28

是否可以在Swift中使用Type作为字典键?

这是可能的,这里有一种方法:

代码语言:javascript
复制
protocol Growable { ... }

struct S : Growable { ... }
class C : Growable { ... }

extension Dictionary where Key : LosslessStringConvertible
{
   subscript(index: Growable.Type) -> Value?
   {
      get
      {
         return self[String(describing: index) as! Key]
      }
      set(newValue)
      {
         self[String(describing: index) as! Key] = newValue
      }
   }
}

var d : [String:Int] = [:]
d[S.self] = 42
d[C.self] = 24
print(d)

指纹:

代码语言:javascript
复制
["C": 24, "S": 42]

如果将subscript定义更改为:

代码语言:javascript
复制
subscript(index: Any.Type) -> Value?

当然,您可以使用任何类型作为键:

代码语言:javascript
复制
var d : [String:Int] = [:]
d[S.self] = 42
d[C.self] = 24
d[type(of:d)] = 18
print(d)

指纹:

代码语言:javascript
复制
["C": 24, "S": 42, "Dictionary<String, Int>": 18]

我让你来决定这是否明智,但这显然是可能的。

[注意:您不能将Key限制为String,因此使用协议LosslessStringConvertible__;可能有更好的选择,Swift标准库是一个移动目标.]

HTH

票数 3
EN

Stack Overflow用户

发布于 2017-10-18 19:35:27

你可以考虑后退一步,回顾一下你的设计。您可以使用枚举(另一个强大的Swift功能)对Growable工厂进行建模。例如:

代码语言:javascript
复制
protocol Growable {
    /* ... */
}

enum Vegetable: String, Hashable, Growable {
    case carrot, lettuce, potato /* ... */
}

enum Mushroom: String, Hashable, Growable {
    /* ... */
}

struct Farm {
    var crops = [AnyHashable: Int]()
    mutating func plant<T: Growable & Hashable>(qty: Int, of growable: T) {
        crops[growable] = qty
    }
}

不支持使用Hashable作为具体类型,因此,我们需要使用类型擦除的AnyHashable结构来代替--具有自或相关类型需求的协议可能很难得到正确的处理!

用法:

代码语言:javascript
复制
var myFarm = Farm()
myFarm.plant(qty: 10, of: Vegetable.carrot)
myFarm.plant(qty: 20, of: Vegetable.lettuce)
myFarm.plant(qty: 30, of: Vegetable.potato)

print(myFarm.crops)

AnyHashable(Vegetable.potato):30,AnyHashable(Vegetable.carrot):10,AnyHashable(Vegetable.lettuce):20

.关于你最初的设计,正确的表达你意图的方法是:

代码语言:javascript
复制
extension Growable.Type: Hashable {
    /* make this meta thing hashable! */
}

也就是说,制作相应的元类型Hashable,但Swift还不支持扩展元类型;)

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46814089

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档