在Swift中,如何扩展一个类型别名?

20

我有一个 typealias:

typealias BeaconId = [String: NSObject]

我希望通过做一些类似以下的事情来扩展它:

extension BeaconId {}

但是这会导致编译错误:

带限制的扩展必须在带有由'where'语句指定的约束条件的未特化泛型类型'Dictionary'上声明

所以最后我做的是:

extension Dictionary where Key: StringLiteralConvertible, Value: NSObject {}

有没有更简洁的方法来做这件事?


1
我试图清理你的代码,但实际上出现了这个错误:受限扩展必须在未指定约束的泛型类型“Dictionary”上声明,该约束由“where”子句指定 - BallpointBen
是的,我也明白了,你可以在下面查看我的完整答案。基本上,似乎不可能扩展指定的泛型类型,只能扩展尚未设置泛型类型的类型。 - barndog
@Robert 我希望在 Swift 3 中看到的不仅是协议和继承上的约束,还包括对值的约束,因此类似于 extension SomeEnum where Self == .MyCase 这样的东西。这样功能就可以仅针对特定的枚举案例进行定义。 - barndog
2个回答

16
< p > 在Swift 4.2时更新:现在您可以这样做

示例:


示例:

typealias KeyedNumbers = [String: Int]

extension KeyedNumbers {
    func squaredValue(forKey key: String) -> Int {
        return self[key]! * self[key]!
    }
}

有了那个(相当没用的)扩展后,你可以这样做:

let pairs = ["two": 2, "three": 3]
print("2 squared =", pairs.squaredValue(forKey: "two"))

它将打印

2的平方等于4


在Swift 5中,似乎原始类型也会得到扩展。例如["two": 2, "three": 3].squaredValue(forKey: "two")是有效的。这在其他情况下可能不是你想要的。 - undefined

4
据我所知,不行。
考虑以下示例:
typealias Height: Float

extension: Height {

}

在这里,Height并不是一个新类型,它只是Float的标签,因此您只是扩展了Float。如果您查看Dictionary,它是public struct Dictionary<Key : Hashable, Value> : CollectionType, DictionaryLiteralConvertible,因此您尝试实现的目标是

extension BeaconID {}

这是在为 Dictionary 添加特定的泛型参数。

我希望您能够做到以下几点:

typealias BeaconID = Dictionary<Key: String, Value: NSObject>

但这也无法编译,原因是在Swift中,您不能typealias部分类型(换句话说,泛型类型没有具体的泛型参数类型。有关更多信息,请参见此处)。下面是解决typealias泛型类型的一个可能方法,它已在我链接的答案下面注明了。

struct Wrapper<Key: Hashable, Value> {
    typealias T = Dictionary<Key, Value>
}
typealias BeaconID = Wrapper<String, NSObject>.T

但是即使你试图扩展BeaconID,你仍然会收到编译器警告,这最终揭示了问题的核心:

"约束扩展必须在未特化泛型类型'Dictionary'上声明,并通过'where'子句指定约束条件"


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接