gpt4 book ai didi

arrays - Swift:扩展 [?] 以生成 [?] 可能吗?

转载 作者:搜寻专家 更新时间:2023-10-30 22:24:50 25 4
gpt4 key购买 nike

在 Swift 中,我有一个具有以下基本前提的自定义结构:

一个包装器结构,可以包含任何符合 BinaryInteger 的类型,例如 Int、UInt8、Int16 等。

protocol SomeTypeProtocol {
associatedtype NumberType

var value: NumberType { get set }
}

struct SomeType<T: BinaryInteger>: SomeTypeProtocol {
typealias NumberType = T

var value: NumberType
}

以及 Collection 的扩展:

extension Collection where Element: SomeTypeProtocol {
var values: [Element.NumberType] {
return self.map { $0.value }
}
}

例如,这很好用:

let arr = [SomeType(value: 123), SomeType(value: 456)]

// this produces [123, 456] of type [Int] since literals are Int by default
arr.values

我想做的是完全相同的事情,但对于 SomeType<T>?

let arr: [SomeType<Int>?] = [SomeType(value: 123), SomeType(value: 456)]

// this doesn't work, obviously
arr.values

// but what I want is this:
arr.values // to produce [Optional(123), Optional(456)]

我已经尝试过无数次尝试来解决这个问题并进行了大量研究,但我希望任何一位 Swift 老手都能对此有所启发。

这是我设想的样子,但这行不通:

extension Collection where Element == Optional<SomeType<T>> {
var values: [T?] {
return self.map { $0?.value }
}
}

这是一种在不使用泛型的情况下实现目标的笨拙方法,但它有效:

extension Collection where Element == Optional<SomeType<Int>> {
var values: [Int?] {
return self.map { $0?.value }
}
}

let arr: [SomeType<Int>?] = [SomeType(value: 123), SomeType(value: 456)]
arr.values // [Optional(123), Optional(456)]

但它需要为每个已知的符合 BinaryInteger 的类型手动编写扩展,并且不会在不手动更新代码的情况下自动包含 future 可能采用 BinaryInteger 的类型。

// "..." would contain the var values code from above, copy-and-pasted
extension Collection where Element == Optional<SomeType<Int>> { ... }
extension Collection where Element == Optional<SomeType<Int8>> { ... }
extension Collection where Element == Optional<SomeType<UInt8>> { ... }
extension Collection where Element == Optional<SomeType<Int16>> { ... }
extension Collection where Element == Optional<SomeType<UInt16>> { ... }
extension Collection where Element == Optional<SomeType<Int32>> { ... }
extension Collection where Element == Optional<SomeType<UInt32>> { ... }
extension Collection where Element == Optional<SomeType<Int64>> { ... }
extension Collection where Element == Optional<SomeType<UInt64>> { ... }

编辑 2018 年 6 月 23 日:

解决方案 #1 - 完全通用但必须是 Func,而不是计算属性

Ole's reply 上展开:

优点:如果 values() 成为 func 而不是计算属性,这是一个优雅的解决方案。

缺点:没有已知的方法可以将此方法实现为计算属性,并且在检查代码中的 values() 时,Swift 的快速帮助弹出窗口会显示 [T] 和 [T?]。即:它只是说 func values<T>() -> [T] where T : BinaryInteger 这不是非常有用或 Swifty。然而,它当然仍然是强类型的。

extension Collection {
func values<T>() -> [T] where Element == SomeType<T> {
return map { $0.value }
}

func values<T>() -> [T?] where Element == SomeType<T>? {
return map { $0?.value }
}
}

解决方案 #2 - 可选协议(protocol)解决方法

Martin's reply 上展开:

优点:允许使用计算属性(最终用户访问更干净,因为它不需要 func parens)并在 Xcode 的快速帮助弹出窗口中显示推断类型。

缺点:从内部代码的角度来看不够优雅,因为它需要一个解决方法。但不一定是缺点。

// Define OptionalType

protocol OptionalType {
associatedtype Wrapped
var asOptional: Wrapped? { get }
}

extension Optional: OptionalType {
var asOptional: Wrapped? {
return self
}
}

// Extend Collection

extension Collection where Element: SomeTypeProtocol {
var values: [Element.NumberType] {
return self.map { $0.value }
}
}

extension Collection where Element: OptionalType, Element.Wrapped: SomeTypeProtocol {
var values: [Element.Wrapped.NumberType?] {
return self.map { $0.asOptional?.value }
}
}

最佳答案

Martin R's answer 是一个很好的解决方案。一个不需要额外标记协议(protocol)的替代方法是:在 Collection 上写一个unconstrained 扩展,并在该扩展中,定义一个 constrainedwhere Element == SomeType<T>? 的通用函数:

extension Collection {
func values<T>() -> [T?] where Element == SomeType<T>? {
return map( { $0?.value })
}
}

这个有效:

let arr: [SomeType<Int>?] = [SomeType(value: 123), SomeType(value: 456)]
arr.values() // [Optional(123), Optional(456)]

您会注意到我使用了 func 而不是计算属性。我无法正确使用通用语法。这不是应该的吗?

extension Collection {
// error: consecutive declarations on a line must be separated by ';'
var values<T>: [T?] where Element == SomeType<T>? {
return self.map( { $0?.value })
}
}

关于arrays - Swift:扩展 [<SomeType<T>?] 以生成 [<T>?] 可能吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50999688/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com